Browse Source

Fixed interaction between snippets with bound elements and Undo/Redo.

pull/14/head
Daniel Grunwald 15 years ago
parent
commit
d5aaa9df39
  1. 3
      data/templates/file/CSharp/CSharp.UnitTest.xft
  2. 6
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
  3. 2
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/DocumentChangeOperation.cs
  4. 5
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs
  5. 5
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/UndoOperationGroup.cs
  6. 63
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/UndoStack.cs

3
data/templates/file/CSharp/CSharp.UnitTest.xft

@ -53,8 +53,7 @@ @@ -53,8 +53,7 @@
<Files>
<File name="${FullName}" language="C#"><![CDATA[${StandardHeader.C#}
<% if (ConditionalClass) { %>#if TEST
<% } %>
using System;
<% } %>using System;
using NUnit.Framework;
namespace ${StandardNamespace}

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

@ -143,8 +143,10 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -143,8 +143,10 @@ namespace ICSharpCode.AvalonEdit.AddIn
if (snippet != null) {
snippet.TrackUsage("CustomTabCommand");
editor.Adapter.Document.Remove(wordStart, editor.CaretOffset - wordStart);
snippet.CreateAvalonEditSnippet(editor.Adapter).Insert(editor.TextArea);
using (editor.Document.RunUpdate()) {
editor.Adapter.Document.Remove(wordStart, editor.CaretOffset - wordStart);
snippet.CreateAvalonEditSnippet(editor.Adapter).Insert(editor.TextArea);
}
return;
}
}

2
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/DocumentChangeOperation.cs

@ -23,6 +23,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -23,6 +23,7 @@ namespace ICSharpCode.AvalonEdit.Document
public void Undo(UndoStack stack)
{
Debug.Assert(stack.state == UndoStack.StatePlayback);
stack.RegisterAffectedDocument(document);
stack.state = UndoStack.StatePlaybackModifyDocument;
this.Undo();
stack.state = UndoStack.StatePlayback;
@ -31,6 +32,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -31,6 +32,7 @@ namespace ICSharpCode.AvalonEdit.Document
public void Redo(UndoStack stack)
{
Debug.Assert(stack.state == UndoStack.StatePlayback);
stack.RegisterAffectedDocument(document);
stack.state = UndoStack.StatePlaybackModifyDocument;
this.Redo();
stack.state = UndoStack.StatePlayback;

5
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs

@ -98,7 +98,6 @@ namespace ICSharpCode.AvalonEdit.Document @@ -98,7 +98,6 @@ namespace ICSharpCode.AvalonEdit.Document
anchorTree = new TextAnchorTree(this);
undoStack = new UndoStack();
undoStack.AttachToDocument(this);
FireChangeEvents();
}
@ -354,6 +353,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -354,6 +353,7 @@ namespace ICSharpCode.AvalonEdit.Document
throw new InvalidOperationException("Cannot change document within another document change.");
beginUpdateCount++;
if (beginUpdateCount == 1) {
undoStack.StartUndoGroup();
if (UpdateStarted != null)
UpdateStarted(this, EventArgs.Empty);
}
@ -374,6 +374,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -374,6 +374,7 @@ namespace ICSharpCode.AvalonEdit.Document
// fire change events inside the change group - event handlers might add additional
// document changes to the change group
FireChangeEvents();
undoStack.EndUndoGroup();
beginUpdateCount = 0;
if (UpdateFinished != null)
UpdateFinished(this, EventArgs.Empty);
@ -590,6 +591,8 @@ namespace ICSharpCode.AvalonEdit.Document @@ -590,6 +591,8 @@ namespace ICSharpCode.AvalonEdit.Document
if (Changing != null)
Changing(this, args);
undoStack.Push(this, args);
cachedText = null; // reset cache of complete document text
fireTextChanged = true;
DelayedEvents delayedEvents = new DelayedEvents();

5
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/UndoOperationGroup.cs

@ -22,9 +22,8 @@ namespace ICSharpCode.AvalonEdit.Document @@ -22,9 +22,8 @@ namespace ICSharpCode.AvalonEdit.Document
}
Debug.Assert(numops > 0 , "UndoOperationGroup : numops should be > 0");
if (numops > stack.Count) {
numops = stack.Count;
}
Debug.Assert(numops <= stack.Count);
undolist = new IUndoableOperation[numops];
for (int i = 0; i < numops; ++i) {
undolist[i] = stack.PopBack();

63
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/UndoStack.cs

@ -2,9 +2,9 @@ @@ -2,9 +2,9 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using ICSharpCode.AvalonEdit.Utils;
namespace ICSharpCode.AvalonEdit.Document
@ -213,6 +213,7 @@ namespace ICSharpCode.AvalonEdit.Document @@ -213,6 +213,7 @@ namespace ICSharpCode.AvalonEdit.Document
undoGroupDepth--;
//Util.LoggingService.Debug("Close undo group (new depth=" + undoGroupDepth + ")");
if (undoGroupDepth == 0) {
Debug.Assert(state == StateListen || actionCountInUndoGroup == 0);
if (actionCountInUndoGroup == optionalActionCount) {
// only optional actions: don't store them
for (int i = 0; i < optionalActionCount; i++) {
@ -223,9 +224,11 @@ namespace ICSharpCode.AvalonEdit.Document @@ -223,9 +224,11 @@ namespace ICSharpCode.AvalonEdit.Document
undostack.PushBack(new UndoOperationGroup(undostack, actionCountInUndoGroup));
FileModified(-actionCountInUndoGroup + 1 + optionalActionCount);
}
//if (state == StateListen) {
EnforceSizeLimit();
allowContinue = true;
RecalcIsOriginalFile(); // can raise event
//}
}
}
@ -243,6 +246,28 @@ namespace ICSharpCode.AvalonEdit.Document @@ -243,6 +246,28 @@ namespace ICSharpCode.AvalonEdit.Document
}
}
List<TextDocument> affectedDocuments;
internal void RegisterAffectedDocument(TextDocument document)
{
if (affectedDocuments == null)
affectedDocuments = new List<TextDocument>();
if (!affectedDocuments.Contains(document)) {
affectedDocuments.Add(document);
document.BeginUpdate();
}
}
void CallEndUpdateOnAffectedDocuments()
{
if (affectedDocuments != null) {
foreach (TextDocument doc in affectedDocuments) {
doc.EndUpdate();
}
affectedDocuments = null;
}
}
/// <summary>
/// Call this method to undo the last operation on the stack
/// </summary>
@ -260,8 +285,9 @@ namespace ICSharpCode.AvalonEdit.Document @@ -260,8 +285,9 @@ namespace ICSharpCode.AvalonEdit.Document
RunUndo(uedit);
} finally {
state = StateListen;
FileModified(-1);
CallEndUpdateOnAffectedDocuments();
}
FileModified(-1);
RecalcIsOriginalFile();
if (undostack.Count == 0)
NotifyPropertyChanged("CanUndo");
@ -294,8 +320,9 @@ namespace ICSharpCode.AvalonEdit.Document @@ -294,8 +320,9 @@ namespace ICSharpCode.AvalonEdit.Document
RunRedo(uedit);
} finally {
state = StateListen;
FileModified(1);
CallEndUpdateOnAffectedDocuments();
}
FileModified(1);
RecalcIsOriginalFile();
if (redostack.Count == 0)
NotifyPropertyChanged("CanRedo");
@ -345,14 +372,15 @@ namespace ICSharpCode.AvalonEdit.Document @@ -345,14 +372,15 @@ namespace ICSharpCode.AvalonEdit.Document
if (state == StateListen && sizeLimit > 0) {
bool wasEmpty = undostack.Count == 0;
StartUndoGroup();
bool needsUndoGroup = undoGroupDepth == 0;
if (needsUndoGroup) StartUndoGroup();
undostack.PushBack(operation);
actionCountInUndoGroup++;
if (isOptional)
optionalActionCount++;
else
FileModified(1);
EndUndoGroup();
if (needsUndoGroup) EndUndoGroup();
if (wasEmpty)
NotifyPropertyChanged("CanUndo");
ClearRedoStack();
@ -390,29 +418,14 @@ namespace ICSharpCode.AvalonEdit.Document @@ -390,29 +418,14 @@ namespace ICSharpCode.AvalonEdit.Document
ClearRedoStack();
}
internal void AttachToDocument(TextDocument document)
{
document.UpdateStarted += document_UpdateStarted;
document.UpdateFinished += document_UpdateFinished;
document.Changing += document_Changing;
}
void document_UpdateStarted(object sender, EventArgs e)
{
StartUndoGroup();
}
void document_UpdateFinished(object sender, EventArgs e)
{
EndUndoGroup();
}
void document_Changing(object sender, DocumentChangeEventArgs e)
internal void Push(TextDocument document, DocumentChangeEventArgs e)
{
if (state == StatePlayback)
throw new InvalidOperationException("Document changes during undo/redo operations are not allowed.");
TextDocument document = (TextDocument)sender;
Push(new DocumentChangeOperation(document, e));
if (state == StatePlaybackModifyDocument)
state = StatePlayback; // allow only 1 change per expected modification
else
Push(new DocumentChangeOperation(document, e));
}
/// <summary>

Loading…
Cancel
Save