diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs index d33469e276..343f8567ff 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs @@ -44,23 +44,36 @@ namespace ICSharpCode.AvalonEdit.AddIn this.Files.Add(file); file.ForceInitializeView(this); - codeEditor.Document.Changed += textEditor_Document_Changed; + file.IsDirtyChanged += PrimaryFile_IsDirtyChanged; + codeEditor.Document.UndoStack.PropertyChanged += codeEditor_Document_UndoStack_PropertyChanged; codeEditor.CaretPositionChanged += CaretChanged; codeEditor.TextCopied += codeEditor_TextCopied; } - void codeEditor_TextCopied(object sender, ICSharpCode.AvalonEdit.Editing.TextEventArgs e) + void codeEditor_Document_UndoStack_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { - TextEditorSideBar.Instance.PutInClipboardRing(e.Text); + PrimaryFile.IsDirty = !codeEditor.Document.UndoStack.IsOriginalFile; } - void textEditor_Document_Changed(object sender, DocumentChangeEventArgs e) + void PrimaryFile_IsDirtyChanged(object sender, EventArgs e) { - if (!isLoading) { - PrimaryFile.IsDirty = true; + var document = codeEditor.Document; + if (document != null) { + var undoStack = document.UndoStack; + if (this.PrimaryFile.IsDirty) { + if (undoStack.IsOriginalFile) + undoStack.DiscardOriginalFileMarker(); + } else { + undoStack.MarkAsOriginalFile(); + } } } + void codeEditor_TextCopied(object sender, ICSharpCode.AvalonEdit.Editing.TextEventArgs e) + { + TextEditorSideBar.Instance.PutInClipboardRing(e.Text); + } + public CodeEditor CodeEditor { get { return codeEditor; } } @@ -221,6 +234,7 @@ namespace ICSharpCode.AvalonEdit.AddIn public override void Dispose() { + this.PrimaryFile.IsDirtyChanged -= PrimaryFile_IsDirtyChanged; base.Dispose(); BookmarksDetach(); codeEditor.Dispose(); diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs index 2120ea0111..81b3bc977b 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs @@ -285,6 +285,7 @@ namespace ICSharpCode.AvalonEdit.AddIn this.Encoding = reader.CurrentEncoding; } } + primaryTextEditor.IsModified = false; NewLineConsistencyCheck.StartConsistencyCheck(this); } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/UndoStack.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/UndoStack.cs index 8e33449270..5386a4776b 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/UndoStack.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/UndoStack.cs @@ -49,11 +49,22 @@ namespace ICSharpCode.AvalonEdit.Document /// int elementsOnUndoUntilOriginalFile; + bool isOriginalFile = true; + /// /// Gets whether the document is currently in its original state (no modifications). /// public bool IsOriginalFile { - get { return elementsOnUndoUntilOriginalFile == 0; } + get { return isOriginalFile; } + } + + void RecalcIsOriginalFile() + { + bool newIsOriginalFile = (elementsOnUndoUntilOriginalFile == 0); + if (newIsOriginalFile != isOriginalFile) { + isOriginalFile = newIsOriginalFile; + NotifyPropertyChanged("IsOriginalFile"); + } } /// @@ -61,10 +72,8 @@ namespace ICSharpCode.AvalonEdit.Document /// public void MarkAsOriginalFile() { - bool oldIsOriginalFile = IsOriginalFile; elementsOnUndoUntilOriginalFile = 0; - if (!oldIsOriginalFile) - NotifyPropertyChanged("IsOriginalFile"); + RecalcIsOriginalFile(); } /// @@ -72,24 +81,20 @@ namespace ICSharpCode.AvalonEdit.Document /// public void DiscardOriginalFileMarker() { - bool oldIsOriginalFile = IsOriginalFile; elementsOnUndoUntilOriginalFile = int.MinValue; - if (oldIsOriginalFile) - NotifyPropertyChanged("IsOriginalFile"); + RecalcIsOriginalFile(); } void FileModified(int newElementsOnUndoStack) { - if (newElementsOnUndoStack == 0 || elementsOnUndoUntilOriginalFile == int.MinValue) + if (elementsOnUndoUntilOriginalFile == int.MinValue) return; - bool oldIsOriginalFile = IsOriginalFile; elementsOnUndoUntilOriginalFile += newElementsOnUndoStack; if (elementsOnUndoUntilOriginalFile > undostack.Count) elementsOnUndoUntilOriginalFile = int.MinValue; - if (oldIsOriginalFile != IsOriginalFile) - NotifyPropertyChanged("IsOriginalFile"); + // don't call RecalcIsOriginalFile(): wait until end of undo group } #endregion @@ -220,11 +225,11 @@ namespace ICSharpCode.AvalonEdit.Document } else if (actionCountInUndoGroup > 1) { // combine all actions within the group into a single grouped action undostack.PushBack(new UndoOperationGroup(undostack, actionCountInUndoGroup)); - actionCountInUndoGroup = 1; // actions were combined + FileModified(-actionCountInUndoGroup + 1 + optionalActionCount); } EnforceSizeLimit(); allowContinue = true; - FileModified(actionCountInUndoGroup); + RecalcIsOriginalFile(); // can raise event } } @@ -261,6 +266,7 @@ namespace ICSharpCode.AvalonEdit.Document state = StateListen; } FileModified(-1); + RecalcIsOriginalFile(); if (undostack.Count == 0) NotifyPropertyChanged("CanUndo"); if (redostack.Count == 1) @@ -294,6 +300,7 @@ namespace ICSharpCode.AvalonEdit.Document state = StateListen; } FileModified(1); + RecalcIsOriginalFile(); if (redostack.Count == 0) NotifyPropertyChanged("CanRedo"); if (undostack.Count == 1) @@ -347,6 +354,8 @@ namespace ICSharpCode.AvalonEdit.Document actionCountInUndoGroup++; if (isOptional) optionalActionCount++; + else + FileModified(1); EndUndoGroup(); if (wasEmpty) NotifyPropertyChanged("CanUndo"); diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditor.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditor.cs index 4cf4930419..e4fbbdd2b1 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditor.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditor.cs @@ -406,7 +406,7 @@ namespace ICSharpCode.AvalonEdit /// public bool IsModified { get { return (bool)GetValue(IsModifiedProperty); } - set { SetValue(IsModifiedProperty, value); } + set { SetValue(IsModifiedProperty, Boxes.Box(value)); } } static void OnIsModifiedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)