Browse Source

properly fix SD-1783 for AvalonEditViewContent (i.e. text files)

4.1
Eusebiu Marcu 15 years ago
parent
commit
77c2869543
  1. 8
      src/AddIns/BackendBindings/Scripting/Test/Utils/MockViewContent.cs
  2. 1
      src/AddIns/BackendBindings/WixBinding/Test/Utils/MockViewContent.cs
  3. 5
      src/AddIns/BackendBindings/WixBinding/Test/Utils/MockWorkbenchWindow.cs
  4. 24
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs
  5. 15
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
  6. 9
      src/AddIns/DisplayBindings/XmlEditor/Test/Utils/MockViewContent.cs
  7. 8
      src/AddIns/Misc/Reports/ICSharpCode.Reports.Addin/Test/Designer/MockViewContend.cs
  8. 15
      src/Main/Base/Project/Src/Gui/AbstractViewContent.cs
  9. 5
      src/Main/Base/Project/Src/Gui/IViewContent.cs
  10. 5
      src/Main/Base/Project/Src/Gui/IWorkbenchWindow.cs
  11. 9
      src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs
  12. 36
      src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs
  13. 9
      src/Main/Base/Project/Src/Util/FakeXmlViewContent.cs

8
src/AddIns/BackendBindings/Scripting/Test/Utils/MockViewContent.cs

@ -26,6 +26,7 @@ namespace ICSharpCode.Scripting.Tests.Utils
public event EventHandler TabPageTextChanged; public event EventHandler TabPageTextChanged;
public event EventHandler Disposed; public event EventHandler Disposed;
public event EventHandler IsDirtyChanged; public event EventHandler IsDirtyChanged;
public event EventHandler IsReadOnlyChanged;
public string TitleName { public string TitleName {
get { get {
@ -234,6 +235,13 @@ namespace ICSharpCode.Scripting.Tests.Utils
} }
} }
protected virtual void OnIsReadOnlyChanged(EventArgs e)
{
if (IsReadOnlyChanged != null) {
IsReadOnlyChanged(this, e);
}
}
public object GetService(Type serviceType) public object GetService(Type serviceType)
{ {
return null; return null;

1
src/AddIns/BackendBindings/WixBinding/Test/Utils/MockViewContent.cs

@ -41,6 +41,7 @@ namespace WixBinding.Tests.Utils
public event EventHandler IsDirtyChanged; public event EventHandler IsDirtyChanged;
public event EventHandler TitleNameChanged; public event EventHandler TitleNameChanged;
public event EventHandler InfoTipChanged; public event EventHandler InfoTipChanged;
public event EventHandler IsReadOnlyChanged;
#pragma warning restore 67 #pragma warning restore 67
public IList<OpenedFile> Files { public IList<OpenedFile> Files {

5
src/AddIns/BackendBindings/WixBinding/Test/Utils/MockWorkbenchWindow.cs

@ -86,10 +86,5 @@ namespace WixBinding.Tests.Utils
TitleChanged(this, e); TitleChanged(this, e);
} }
} }
public void RefreshStatus()
{
throw new NotImplementedException();
}
} }
} }

24
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs

@ -5,15 +5,12 @@ using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.AddIn.Options; using ICSharpCode.AvalonEdit.AddIn.Options;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Bookmarks; using ICSharpCode.SharpDevelop.Bookmarks;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
@ -53,6 +50,21 @@ namespace ICSharpCode.AvalonEdit.AddIn
codeEditor.Document.UndoStack.PropertyChanged += codeEditor_Document_UndoStack_PropertyChanged; codeEditor.Document.UndoStack.PropertyChanged += codeEditor_Document_UndoStack_PropertyChanged;
codeEditor.CaretPositionChanged += CaretChanged; codeEditor.CaretPositionChanged += CaretChanged;
codeEditor.TextCopied += codeEditor_TextCopied; codeEditor.TextCopied += codeEditor_TextCopied;
// get the watcher for the file
var watcher = FileChangeWatcher.ActiveWatchers.FirstOrDefault(w => w.File == file);
if (watcher != null)
watcher.FileChanged += OnFileExternallyChanged;
}
void OnFileExternallyChanged(object sender, EventArgs e)
{
// handle readonly
bool isExternalReadOnly = (File.GetAttributes(this.PrimaryFileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;
if (isExternalReadOnly != IsReadOnly) {
codeEditor.PrimaryTextEditor.IsReadOnly = isExternalReadOnly;
OnIsReadOnlyChanged(EventArgs.Empty);
}
} }
void codeEditor_Document_UndoStack_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) void codeEditor_Document_UndoStack_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
@ -139,6 +151,10 @@ namespace ICSharpCode.AvalonEdit.AddIn
codeEditor.SyntaxHighlighting = codeEditor.SyntaxHighlighting =
HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(file.FileName)); HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(file.FileName));
if (!file.IsUntitled) {
codeEditor.PrimaryTextEditor.IsReadOnly = (File.GetAttributes(file.FileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;
}
codeEditor.Load(stream); codeEditor.Load(stream);
// Load() causes the undo stack to think stuff changed, so re-mark the file as original if necessary // Load() causes the undo stack to think stuff changed, so re-mark the file as original if necessary
if (!this.PrimaryFile.IsDirty) { if (!this.PrimaryFile.IsDirty) {

15
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs

@ -84,21 +84,6 @@ namespace ICSharpCode.AvalonEdit.AddIn
get { return this.Adapter.FileName; } get { return this.Adapter.FileName; }
} }
public new bool IsReadOnly {
get {
if (!File.Exists(FileName))
return base.IsReadOnly;
if ((File.GetAttributes(FileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
return true;
return base.IsReadOnly;
}
set {
base.IsReadOnly = value;
}
}
protected override void OnOptionChanged(PropertyChangedEventArgs e) protected override void OnOptionChanged(PropertyChangedEventArgs e)
{ {
base.OnOptionChanged(e); base.OnOptionChanged(e);

9
src/AddIns/DisplayBindings/XmlEditor/Test/Utils/MockViewContent.cs

@ -53,6 +53,15 @@ namespace XmlEditor.Tests.Utils
} }
} }
public event EventHandler IsReadOnlyChanged;
protected virtual void OnIsReadOnlyChanged(EventArgs e)
{
if (IsReadOnlyChanged != null) {
IsReadOnlyChanged(this, e);
}
}
public object Control { public object Control {
get { get {
throw new NotImplementedException(); throw new NotImplementedException();

8
src/AddIns/Misc/Reports/ICSharpCode.Reports.Addin/Test/Designer/MockViewContend.cs

@ -28,6 +28,7 @@ namespace ICSharpCode.Reports.Addin.Test.Designer
public event EventHandler TabPageTextChanged; public event EventHandler TabPageTextChanged;
public event EventHandler Disposed; public event EventHandler Disposed;
public event EventHandler IsDirtyChanged; public event EventHandler IsDirtyChanged;
public event EventHandler IsReadOnlyChanged;
public object Control public object Control
{ {
@ -230,6 +231,13 @@ namespace ICSharpCode.Reports.Addin.Test.Designer
} }
} }
protected virtual void OnIsReadOnlyChanged(EventArgs e)
{
if (IsReadOnlyChanged != null) {
IsReadOnlyChanged(this, e);
}
}
public object InitiallyFocusedControl { public object InitiallyFocusedControl {
get { get {
throw new NotImplementedException(); throw new NotImplementedException();

15
src/Main/Base/Project/Src/Gui/AbstractViewContent.cs

@ -2,11 +2,10 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.ComponentModel.Design;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel.Design;
using System.IO; using System.IO;
using System.Windows.Forms;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.Presentation; using ICSharpCode.Core.Presentation;
@ -393,7 +392,6 @@ namespace ICSharpCode.SharpDevelop.Gui
} }
#endregion #endregion
#region InfoTip #region InfoTip
public event EventHandler InfoTipChanged; public event EventHandler InfoTipChanged;
@ -608,6 +606,7 @@ namespace ICSharpCode.SharpDevelop.Gui
return null; return null;
} }
#region Read only
/// <summary> /// <summary>
/// Gets if the view content is read-only (can be saved only when choosing another file name). /// Gets if the view content is read-only (can be saved only when choosing another file name).
/// </summary> /// </summary>
@ -615,6 +614,16 @@ namespace ICSharpCode.SharpDevelop.Gui
get { return false; } get { return false; }
} }
public event EventHandler IsReadOnlyChanged;
protected virtual void OnIsReadOnlyChanged(EventArgs e)
{
if (IsReadOnlyChanged != null) {
IsReadOnlyChanged(this, e);
}
}
#endregion
/// <summary> /// <summary>
/// Gets if the view content is view-only (cannot be saved at all). /// Gets if the view content is view-only (cannot be saved at all).
/// </summary> /// </summary>

5
src/Main/Base/Project/Src/Gui/IViewContent.cs

@ -145,6 +145,11 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
bool IsReadOnly { get; } bool IsReadOnly { get; }
/// <summary>
/// Is called each time the IsReadonly for the content has changed.
/// </summary>
event EventHandler IsReadOnlyChanged;
/// <summary> /// <summary>
/// Gets if the view content is view-only (cannot be saved at all). /// Gets if the view content is view-only (cannot be saved at all).
/// </summary> /// </summary>

5
src/Main/Base/Project/Src/Gui/IWorkbenchWindow.cs

@ -72,11 +72,6 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
void SelectWindow(); void SelectWindow();
/// <summary>
/// Refresh window status: title, infotip, lock.
/// </summary>
void RefreshStatus();
/// <summary> /// <summary>
/// Is called when the title of this window has changed. /// Is called when the title of this window has changed.
/// </summary> /// </summary>

9
src/Main/Base/Project/Src/Gui/Workbench/Layouts/AvalonWorkbenchWindow.cs

@ -145,8 +145,10 @@ namespace ICSharpCode.SharpDevelop.Gui
UpdateTitleAndInfoTip(); UpdateTitleAndInfoTip();
IViewContent newActiveViewContent = this.ActiveViewContent; IViewContent newActiveViewContent = this.ActiveViewContent;
if (newActiveViewContent != null) if (newActiveViewContent != null) {
IsLocked = newActiveViewContent.IsReadOnly; IsLocked = newActiveViewContent.IsReadOnly;
newActiveViewContent.IsReadOnlyChanged += delegate { IsLocked = newActiveViewContent.IsReadOnly; };
}
if (oldActiveViewContent != newActiveViewContent && ActiveViewContentChanged != null) { if (oldActiveViewContent != newActiveViewContent && ActiveViewContentChanged != null) {
ActiveViewContentChanged(this, EventArgs.Empty); ActiveViewContentChanged(this, EventArgs.Empty);
@ -267,11 +269,6 @@ namespace ICSharpCode.SharpDevelop.Gui
Activate();//this.SetAsActive(); Activate();//this.SetAsActive();
} }
public void RefreshStatus()
{
UpdateActiveViewContent();
}
public override void OnApplyTemplate() public override void OnApplyTemplate()
{ {
base.OnApplyTemplate(); base.OnApplyTemplate();

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

@ -11,7 +11,7 @@ using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop namespace ICSharpCode.SharpDevelop
{ {
internal sealed class FileChangeWatcher : IDisposable public sealed class FileChangeWatcher : IDisposable
{ {
public static bool DetectExternalChangesOption { public static bool DetectExternalChangesOption {
get { get {
@ -37,6 +37,10 @@ namespace ICSharpCode.SharpDevelop
static HashSet<FileChangeWatcher> activeWatchers = new HashSet<FileChangeWatcher>(); static HashSet<FileChangeWatcher> activeWatchers = new HashSet<FileChangeWatcher>();
public static HashSet<FileChangeWatcher> ActiveWatchers {
get { return activeWatchers; }
}
static int globalDisableCount; static int globalDisableCount;
public static void DisableAllChangeWatchers() public static void DisableAllChangeWatchers()
@ -57,9 +61,23 @@ namespace ICSharpCode.SharpDevelop
w.SetWatcher(); w.SetWatcher();
} }
public event EventHandler FileChanged;
void OnFileChanged(EventArgs e)
{
if (FileChanged != null) {
FileChanged(this, e);
}
}
FileSystemWatcher watcher; FileSystemWatcher watcher;
bool wasChangedExternally = false; bool wasChangedExternally = false;
OpenedFile file; OpenedFile file;
bool isFileReadOnly;
public OpenedFile File {
get { return file; }
}
public FileChangeWatcher(OpenedFile file) public FileChangeWatcher(OpenedFile file)
{ {
@ -70,6 +88,8 @@ namespace ICSharpCode.SharpDevelop
file.FileNameChanged += file_FileNameChanged; file.FileNameChanged += file_FileNameChanged;
activeWatchers.Add(this); activeWatchers.Add(this);
SetWatcher(); SetWatcher();
isFileReadOnly = (System.IO.File.GetAttributes(this.file.FileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;
} }
void file_FileNameChanged(object sender, EventArgs e) void file_FileNameChanged(object sender, EventArgs e)
@ -165,6 +185,14 @@ namespace ICSharpCode.SharpDevelop
LoggingService.Debug("File " + file.FileName + " was changed externally: " + e.ChangeType); LoggingService.Debug("File " + file.FileName + " was changed externally: " + e.ChangeType);
if (!wasChangedExternally) { if (!wasChangedExternally) {
wasChangedExternally = true; wasChangedExternally = true;
OnFileChanged(EventArgs.Empty);
// if the file was only made readonly, don't prevent reloading it from disk
bool readOnly = (System.IO.File.GetAttributes(this.file.FileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;
if (readOnly != isFileReadOnly)
wasChangedExternally = false;
isFileReadOnly = readOnly;
if (WorkbenchSingleton.Workbench.IsActiveWindow) { if (WorkbenchSingleton.Workbench.IsActiveWindow) {
// delay reloading message a bit, prevents showing two messages // delay reloading message a bit, prevents showing two messages
// when the file changes twice in quick succession; and prevents // when the file changes twice in quick succession; and prevents
@ -174,8 +202,6 @@ namespace ICSharpCode.SharpDevelop
delegate { MainForm_Activated(this, EventArgs.Empty); } ); delegate { MainForm_Activated(this, EventArgs.Empty); } );
} }
} }
file.RegisteredViewContents.ForEach(vc => vc.WorkbenchWindow.RefreshStatus());
} }
void MainForm_Activated(object sender, EventArgs e) void MainForm_Activated(object sender, EventArgs e)
@ -187,14 +213,14 @@ namespace ICSharpCode.SharpDevelop
return; return;
string fileName = file.FileName; string fileName = file.FileName;
if (!File.Exists(fileName)) if (!System.IO.File.Exists(fileName))
return; return;
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 && file.IsDirty == false) if ((AutoLoadExternalChangesOption && file.IsDirty == false)
|| MessageService.AskQuestion(message, StringParser.Parse("${res:MainWindow.DialogName}"))) || MessageService.AskQuestion(message, StringParser.Parse("${res:MainWindow.DialogName}")))
{ {
if (File.Exists(fileName)) { if (System.IO.File.Exists(fileName)) {
file.ReloadFromDisk(); file.ReloadFromDisk();
} }
} else { } else {

9
src/Main/Base/Project/Src/Util/FakeXmlViewContent.cs

@ -213,5 +213,14 @@ namespace ICSharpCode.SharpDevelop.Util
return null; return null;
} }
#endregion #endregion
public event EventHandler IsReadOnlyChanged;
protected void OnIsReadOnlyChanged(EventArgs e)
{
if (IsReadOnlyChanged != null) {
IsReadOnlyChanged(this, e);
}
}
} }
} }

Loading…
Cancel
Save