Browse Source

fix some bugs in ChangeMarkerMargin

4.1
Siegfried Pammer 15 years ago
parent
commit
429f0229b5
  1. 34
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChangeMarkerMargin.cs
  2. 40
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs
  3. 34
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/LineChangeInfo.cs
  4. 29
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/CompressingTreeList.cs

34
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChangeMarkerMargin.cs

@ -158,6 +158,17 @@ namespace ICSharpCode.AvalonEdit.AddIn
} }
if (oldText != null) { if (oldText != null) {
// TODO : deletions on line 0 cannot be displayed.
LineChangeInfo currLineInfo = changeWatcher.GetChange(startLine);
if (currLineInfo.Change == ChangeType.Deleted) {
var docLine = editor.Document.GetLineByNumber(startLine);
if (docLine.DelimiterLength == 0)
oldText = DocumentUtilitites.GetLineTerminator(changeWatcher.CurrentDocument, startLine);
oldText = editor.Document.GetText(docLine.Offset, docLine.TotalLength) + oldText;
}
DiffControl differ = new DiffControl(); DiffControl differ = new DiffControl();
differ.editor.SyntaxHighlighting = editor.SyntaxHighlighting; differ.editor.SyntaxHighlighting = editor.SyntaxHighlighting;
differ.editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; differ.editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
@ -165,16 +176,6 @@ namespace ICSharpCode.AvalonEdit.AddIn
differ.editor.Document.Text = oldText; differ.editor.Document.Text = oldText;
differ.Background = Brushes.White; differ.Background = Brushes.White;
// TODO : deletions on line 0 cannot be displayed.
LineChangeInfo prevLineInfo = changeWatcher.GetChange(startLine - 1);
LineChangeInfo lineInfo = changeWatcher.GetChange(startLine);
if (prevLineInfo.Change == ChangeType.Deleted) {
var docLine = editor.Document.GetLineByNumber(startLine - 1);
differ.editor.Document.Insert(0, editor.Document.GetText(docLine.Offset, docLine.TotalLength));
}
if (oldText == string.Empty) { if (oldText == string.Empty) {
differ.editor.Visibility = Visibility.Collapsed; differ.editor.Visibility = Visibility.Collapsed;
differ.copyButton.Visibility = Visibility.Collapsed; differ.copyButton.Visibility = Visibility.Collapsed;
@ -184,22 +185,13 @@ namespace ICSharpCode.AvalonEdit.AddIn
var mainHighlighter = new DocumentHighlighter(baseDocument, differ.editor.SyntaxHighlighting.MainRuleSet); var mainHighlighter = new DocumentHighlighter(baseDocument, differ.editor.SyntaxHighlighting.MainRuleSet);
var popupHighlighter = differ.editor.TextArea.GetService(typeof(IHighlighter)) as DocumentHighlighter; var popupHighlighter = differ.editor.TextArea.GetService(typeof(IHighlighter)) as DocumentHighlighter;
if (prevLineInfo.Change == ChangeType.Deleted) popupHighlighter.InitialSpanStack = mainHighlighter.GetSpanStack(currLineInfo.OldStartLineNumber);
popupHighlighter.InitialSpanStack = mainHighlighter.GetSpanStack(prevLineInfo.OldStartLineNumber);
else
popupHighlighter.InitialSpanStack = mainHighlighter.GetSpanStack(lineInfo.OldStartLineNumber);
} }
} }
differ.revertButton.Click += delegate { differ.revertButton.Click += delegate {
if (hasNewVersion) { if (hasNewVersion) {
int delimiter = 0; Document.Replace(offset, length, oldText);
DocumentLine l = Document.GetLineByOffset(offset + length);
if (added)
delimiter = l.DelimiterLength;
if (length == 0)
oldText += DocumentUtilitites.GetLineTerminator(new AvalonEditDocumentAdapter(Document, null), l.LineNumber);
Document.Replace(offset, length + delimiter, oldText);
tooltip.IsOpen = false; tooltip.IsOpen = false;
} }
}; };

40
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs

@ -81,7 +81,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
if (update) if (update)
changeList.Transform(TransformLineChangeInfo); changeList.Transform(TransformLineChangeInfo);
else else
changeList.InsertRange(0, document.TotalNumberOfLines + 1, LineChangeInfo.Empty); changeList.InsertRange(0, document.TotalNumberOfLines + 1, LineChangeInfo.EMPTY);
} else { } else {
changeList.Clear(); changeList.Clear();
@ -92,25 +92,23 @@ namespace ICSharpCode.AvalonEdit.AddIn
new DocumentSequence(document, hashes) new DocumentSequence(document, hashes)
); );
changeList.Add(LineChangeInfo.Empty); changeList.Add(LineChangeInfo.EMPTY);
int lastEndLine = 0; int lastEndLine = 0;
foreach (Edit edit in diff.GetEdits()) { foreach (Edit edit in diff.GetEdits()) {
int beginLine = edit.BeginB; int beginLine = edit.BeginB;
int endLine = edit.EndB; int endLine = edit.EndB;
changeList.InsertRange(changeList.Count, beginLine - lastEndLine, LineChangeInfo.Empty); changeList.InsertRange(changeList.Count, beginLine - lastEndLine, LineChangeInfo.EMPTY);
LineChangeInfo change = new LineChangeInfo(edit.EditType, edit.BeginA, edit.BeginB, edit.EndA, edit.EndB);
if (endLine == beginLine) if (endLine == beginLine)
changeList[changeList.Count - 1] = change; changeList[changeList.Count - 1] = new LineChangeInfo(edit.EditType, edit.BeginA, edit.EndA);
else else
changeList.InsertRange(changeList.Count, endLine - beginLine, change); changeList.InsertRange(changeList.Count, endLine - beginLine, new LineChangeInfo(edit.EditType, edit.BeginA, edit.EndA));
lastEndLine = endLine; lastEndLine = endLine;
} }
changeList.InsertRange(changeList.Count, textDocument.LineCount - lastEndLine, LineChangeInfo.Empty); changeList.InsertRange(changeList.Count, textDocument.LineCount - lastEndLine, LineChangeInfo.EMPTY);
} }
OnChangeOccurred(EventArgs.Empty); OnChangeOccurred(EventArgs.Empty);
@ -158,7 +156,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
void ILineTracker.LineInserted(DocumentLine insertionPos, DocumentLine newLine) void ILineTracker.LineInserted(DocumentLine insertionPos, DocumentLine newLine)
{ {
int index = insertionPos.LineNumber; int index = insertionPos.LineNumber;
var newLineInfo = new LineChangeInfo(ChangeType.Unsaved, index, index, newLine.LineNumber, newLine.LineNumber); var newLineInfo = new LineChangeInfo(ChangeType.Unsaved, index, index);
changeList[index] = newLineInfo; changeList[index] = newLineInfo;
changeList.Insert(index + 1, newLineInfo); changeList.Insert(index + 1, newLineInfo);
@ -167,7 +165,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
void ILineTracker.RebuildDocument() void ILineTracker.RebuildDocument()
{ {
changeList.Clear(); changeList.Clear();
changeList.InsertRange(0, document.TotalNumberOfLines + 1, new LineChangeInfo(ChangeType.Unsaved, 1, 1, baseDocument.TotalNumberOfLines, document.TotalNumberOfLines)); changeList.InsertRange(0, document.TotalNumberOfLines + 1, new LineChangeInfo(ChangeType.Unsaved, 1, baseDocument.TotalNumberOfLines));
} }
bool disposed = false; bool disposed = false;
@ -188,7 +186,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
added = info.Change == ChangeType.Added; added = info.Change == ChangeType.Added;
if (info.Change != ChangeType.None && info.Change != ChangeType.Unsaved) { if (info.Change != ChangeType.None && info.Change != ChangeType.Unsaved) {
newStartLine = info.NewStartLineNumber + 1; newStartLine = CalculateNewStartLineNumber(lineNumber);
if (info.Change == ChangeType.Added) if (info.Change == ChangeType.Added)
return ""; return "";
@ -196,23 +194,37 @@ namespace ICSharpCode.AvalonEdit.AddIn
var startDocumentLine = baseDocument.GetLine(info.OldStartLineNumber + 1); var startDocumentLine = baseDocument.GetLine(info.OldStartLineNumber + 1);
var endLine = baseDocument.GetLine(info.OldEndLineNumber); var endLine = baseDocument.GetLine(info.OldEndLineNumber);
return baseDocument.GetText(startDocumentLine.Offset, endLine.EndOffset - startDocumentLine.Offset); return TextUtilities.NormalizeNewLines(baseDocument.GetText(startDocumentLine.Offset, endLine.EndOffset - startDocumentLine.Offset), DocumentUtilitites.GetLineTerminator(document, newStartLine));
} }
newStartLine = 0; newStartLine = 0;
return null; return null;
} }
int CalculateNewStartLineNumber(int lineNumber)
{
return changeList.GetStartOfRun(lineNumber);
}
int CalculateNewEndLineNumber(int lineNumber)
{
return changeList.GetEndOfRun(lineNumber) - 1;
}
public bool GetNewVersionFromLine(int lineNumber, out int offset, out int length) public bool GetNewVersionFromLine(int lineNumber, out int offset, out int length)
{ {
LineChangeInfo info = changeList[lineNumber]; LineChangeInfo info = changeList[lineNumber];
if (info.Change != ChangeType.None && info.Change != ChangeType.Unsaved) { if (info.Change != ChangeType.None && info.Change != ChangeType.Unsaved) {
var startLine = document.GetLine(info.NewStartLineNumber + 1); var startLine = document.GetLine(CalculateNewStartLineNumber(lineNumber));
var endLine = document.GetLine(info.NewEndLineNumber); var endLine = document.GetLine(CalculateNewEndLineNumber(lineNumber));
offset = startLine.Offset; offset = startLine.Offset;
length = endLine.EndOffset - startLine.Offset; length = endLine.EndOffset - startLine.Offset;
if (info.Change == ChangeType.Added)
length += endLine.DelimiterLength;
return true; return true;
} }

34
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/LineChangeInfo.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
namespace ICSharpCode.AvalonEdit.AddIn namespace ICSharpCode.AvalonEdit.AddIn
@ -34,7 +35,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
public struct LineChangeInfo : IEquatable<LineChangeInfo> public struct LineChangeInfo : IEquatable<LineChangeInfo>
{ {
public static readonly LineChangeInfo Empty = new LineChangeInfo(ChangeType.None, -1, -1, -1, -1); public static readonly LineChangeInfo EMPTY = new LineChangeInfo(ChangeType.None, -1, -1);
ChangeType change; ChangeType change;
@ -47,37 +48,19 @@ namespace ICSharpCode.AvalonEdit.AddIn
public int OldStartLineNumber { public int OldStartLineNumber {
get { return oldStartLineNumber; } get { return oldStartLineNumber; }
set { oldStartLineNumber = value; }
}
int newStartLineNumber;
public int NewStartLineNumber {
get { return newStartLineNumber; }
set { newStartLineNumber = value; }
} }
int oldEndLineNumber; int oldEndLineNumber;
public int OldEndLineNumber { public int OldEndLineNumber {
get { return oldEndLineNumber; } get { return oldEndLineNumber; }
set { oldEndLineNumber = value; }
} }
int newEndLineNumber; public LineChangeInfo(ChangeType change, int oldStartLineNumber, int oldEndLineNumber)
public int NewEndLineNumber {
get { return newEndLineNumber; }
set { newEndLineNumber = value; }
}
public LineChangeInfo(ChangeType change, int oldStartLineNumber, int newStartLineNumber, int oldEndLineNumber, int newEndLineNumber)
{ {
this.change = change; this.change = change;
this.oldStartLineNumber = oldStartLineNumber; this.oldStartLineNumber = oldStartLineNumber;
this.newStartLineNumber = newStartLineNumber;
this.oldEndLineNumber = oldEndLineNumber; this.oldEndLineNumber = oldEndLineNumber;
this.newEndLineNumber = newEndLineNumber;
} }
#region Equals and GetHashCode implementation #region Equals and GetHashCode implementation
@ -88,11 +71,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
public bool Equals(LineChangeInfo other) public bool Equals(LineChangeInfo other)
{ {
return this.change == other.change && return this.change == other.change && this.oldStartLineNumber == other.oldStartLineNumber && this.oldEndLineNumber == other.oldEndLineNumber;
this.oldEndLineNumber == other.oldEndLineNumber &&
this.newStartLineNumber == other.newStartLineNumber &&
this.oldStartLineNumber == other.oldStartLineNumber &&
this.newEndLineNumber == other.newEndLineNumber;
} }
public override int GetHashCode() public override int GetHashCode()
@ -101,9 +80,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
unchecked { unchecked {
hashCode += 1000000007 * change.GetHashCode(); hashCode += 1000000007 * change.GetHashCode();
hashCode += 1000000009 * oldStartLineNumber.GetHashCode(); hashCode += 1000000009 * oldStartLineNumber.GetHashCode();
hashCode += 1000000021 * newStartLineNumber.GetHashCode(); hashCode += 1000000021 * oldEndLineNumber.GetHashCode();
hashCode += 1000000033 * oldEndLineNumber.GetHashCode();
hashCode += 1000000087 * newEndLineNumber.GetHashCode();
} }
return hashCode; return hashCode;
} }
@ -118,5 +95,6 @@ namespace ICSharpCode.AvalonEdit.AddIn
return !(lhs == rhs); return !(lhs == rhs);
} }
#endregion #endregion
} }
} }

29
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/CompressingTreeList.cs

@ -343,9 +343,38 @@ namespace ICSharpCode.AvalonEdit.Utils
return -1; return -1;
} }
/// <summary>
/// Gets the the first index so that all values from the result index to <paramref name="index"/>
/// are equal.
/// </summary>
public int GetStartOfRun(int index)
{
if (index < 0 || index >= this.Count)
throw new ArgumentOutOfRangeException("index", index, "Value must be between 0 and " + (this.Count - 1));
int indexInRun = index;
GetNode(ref indexInRun);
return index - indexInRun;
}
/// <summary>
/// Gets the first index after <paramref name="index"/> so that the value at the result index is not
/// equal to the value at <paramref name="index"/>.
/// That is, this method returns the exclusive end index of the run of equal values.
/// </summary>
public int GetEndOfRun(int index)
{
if (index < 0 || index >= this.Count)
throw new ArgumentOutOfRangeException("index", index, "Value must be between 0 and " + (this.Count - 1));
int indexInRun = index;
int runLength = GetNode(ref indexInRun).count;
return index - indexInRun + runLength;
}
/// <summary> /// <summary>
/// Gets the number of elements after <paramref name="index"/> that have the same value as each other. /// Gets the number of elements after <paramref name="index"/> that have the same value as each other.
/// </summary> /// </summary>
[Obsolete("This method may be confusing as it returns only the remaining run length after index. " +
"Use GetStartOfRun/GetEndOfRun instead.")]
public int GetRunLength(int index) public int GetRunLength(int index)
{ {
if (index < 0 || index >= this.Count) if (index < 0 || index >= this.Count)

Loading…
Cancel
Save