Browse Source

ChangeMarkerMargin: optimized refresh performance on load and save

pull/15/head
Siegfried Pammer 15 years ago
parent
commit
e3e72b80e6
  1. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChangeMarkerMargin.cs
  2. 88
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs
  3. 13
      src/AddIns/VersionControl/GitAddIn/Src/GitVersionProvider.cs
  4. 20
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/CompressingTreeList.cs
  5. 2
      src/Main/Base/Project/Src/Editor/IDocumentBaseVersionProvider.cs

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

@ -47,7 +47,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -47,7 +47,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
drawingContext.DrawRectangle(Brushes.LightGreen, null, rect);
break;
case ChangeType.Modified:
drawingContext.DrawRectangle(Brushes.Blue, null, rect);
drawingContext.DrawRectangle(Brushes.LightBlue, null, rect);
break;
case ChangeType.Unsaved:
drawingContext.DrawRectangle(Brushes.Yellow, null, rect);

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

@ -24,6 +24,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -24,6 +24,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
CompressingTreeList<LineChangeInfo> changeList;
IDocument document;
TextDocument textDocument;
IDocument baseDocument;
public event EventHandler ChangeOccurred;
@ -51,44 +52,69 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -51,44 +52,69 @@ namespace ICSharpCode.AvalonEdit.AddIn
this.textDocument = ((TextView)document.GetService(typeof(TextView))).Document;
this.changeList = new CompressingTreeList<LineChangeInfo>((x, y) => x.Equals(y));
SetupInitialFileState();
Stream baseFileStream = GetBaseVersion();
if (baseFileStream != null)
baseDocument = DocumentUtilitites.LoadReadOnlyDocumentFromBuffer(new StringTextBuffer(ReadAll(baseFileStream)));
SetupInitialFileState(false);
lineTracker = WeakLineTracker.Register(this.textDocument, this);
this.textDocument.UndoStack.PropertyChanged += UndoStackPropertyChanged;
}
void SetupInitialFileState()
LineChangeInfo TransformLineChangeInfo(LineChangeInfo info)
{
changeList.Clear();
if (info.Change == ChangeType.Unsaved)
info.Change = ChangeType.Added;
Stream baseFileStream = GetBaseVersion();
string baseFile = ReadAll(baseFileStream);
MyersDiff.MyersDiff diff = new MyersDiff.MyersDiff(
new StringSequence(baseFile),
new StringSequence(textDocument.Text)
);
if (diff == null)
changeList.InsertRange(0, document.TotalNumberOfLines + 1, new LineChangeInfo(ChangeType.None, ""));
else {
return info;
}
void SetupInitialFileState(bool update)
{
if (baseDocument == null) {
if (update)
changeList.Transform(TransformLineChangeInfo);
else
changeList.InsertRange(0, document.TotalNumberOfLines + 1, new LineChangeInfo(ChangeType.None, ""));
}else {
changeList.Clear();
MyersDiff.MyersDiff diff = new MyersDiff.MyersDiff(
new DocumentSequence(baseDocument),
new DocumentSequence(document)
);
changeList.Add(new LineChangeInfo(ChangeType.None, ""));
int lastEndLine = 0;
foreach (Edit edit in diff.GetEdits()) {
Console.WriteLine(edit);
int beginLine = textDocument.GetLineByOffset(edit.BeginB).LineNumber;
int endLine = textDocument.GetLineByOffset(edit.EndB).LineNumber;
changeList.InsertRange(changeList.Count, beginLine - lastEndLine, new LineChangeInfo(ChangeType.None, ""));
int beginLine = edit.BeginB;
int endLine = edit.EndB;
changeList.InsertRange(changeList.Count, beginLine - lastEndLine, LineChangeInfo.Empty);
if (edit.EditType == ChangeType.Deleted) {
LineChangeInfo change = changeList[beginLine];
change.DeletedLinesAfterThisLine += baseFile.Substring(edit.BeginA, edit.EndA - edit.BeginA);
for (int i = edit.BeginA; i < edit.EndA; i++) {
var line = baseDocument.GetLine(i + 1);
change.DeletedLinesAfterThisLine += line.Text;
}
changeList[beginLine] = change;
} else
changeList.InsertRange(changeList.Count, endLine - beginLine, new LineChangeInfo(edit.EditType, ""));
} else {
var change = new LineChangeInfo(edit.EditType, "");
changeList.InsertRange(changeList.Count, endLine - beginLine, change);
}
lastEndLine = endLine;
}
changeList.InsertRange(changeList.Count, textDocument.LineCount - lastEndLine, new LineChangeInfo(ChangeType.None, ""));
changeList.InsertRange(changeList.Count, textDocument.LineCount - lastEndLine, LineChangeInfo.Empty);
}
OnChangeOccurred(EventArgs.Empty);
@ -111,30 +137,18 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -111,30 +137,18 @@ namespace ICSharpCode.AvalonEdit.AddIn
return result;
}
return new DefaultVersionProvider().OpenBaseVersion(fileName);
return null;
}
void UndoStackPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (textDocument.UndoStack.IsOriginalFile)
SetupInitialFileState();
SetupInitialFileState(true);
}
void ILineTracker.BeforeRemoveLine(DocumentLine line)
{
int index = line.LineNumber;
LineChangeInfo info = changeList[index];
LineChangeInfo lineBefore = changeList[index - 1];
// TODO : add deleted text (GetText not allowed in ILineTracker callbacks)
// lineBefore.DeletedLinesAfterThisLine
// += (textDocument.GetText(line.Offset, line.Length)
// + Environment.NewLine + info.DeletedLinesAfterThisLine);
//
// Debug.Assert(lineBefore.DeletedLinesAfterThisLine.EndsWith(Environment.NewLine));
changeList[index - 1] = lineBefore;
changeList.RemoveAt(index);
changeList.RemoveAt(line.LineNumber);
}
void ILineTracker.SetLineLength(DocumentLine line, int newTotalLength)
@ -160,6 +174,8 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -160,6 +174,8 @@ namespace ICSharpCode.AvalonEdit.AddIn
void ILineTracker.RebuildDocument()
{
changeList.Clear();
changeList.InsertRange(0, document.TotalNumberOfLines + 1, new LineChangeInfo(ChangeType.Unsaved, ""));
}
bool disposed = false;

13
src/AddIns/VersionControl/GitAddIn/Src/GitVersionProvider.cs

@ -87,13 +87,20 @@ namespace ICSharpCode.GitAddIn @@ -87,13 +87,20 @@ namespace ICSharpCode.GitAddIn
runner.Start("cmd", "/c git ls-tree HEAD " + Path.GetFileName(fileName));
runner.WaitForExit();
return runner.StandardOutput
.Trim()
.Split(new[] { " ", "\t" }, StringSplitOptions.RemoveEmptyEntries)[2];
string output = runner.StandardOutput.Trim();
string[] parts = output.Split(new[] { " ", "\t" }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length < 3)
return null;
return parts[2];
}
Stream OpenOutput(string fileName, string blobHash)
{
if (blobHash == null)
return null;
AnonymousPipeServerStream pipe = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable);
StartupInfo startupInfo = new GitVersionProvider.StartupInfo();

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

@ -353,6 +353,26 @@ namespace ICSharpCode.AvalonEdit.Utils @@ -353,6 +353,26 @@ namespace ICSharpCode.AvalonEdit.Utils
return GetNode(ref index).count - index;
}
/// <summary>
/// Applies the conversion function to all elements in this CompressingTreeList.
/// </summary>
public void Transform(Func<T, T> converter)
{
if (root == null)
return;
Node prevNode = null;
for (Node n = root.LeftMost; n != null; n = n.Successor) {
n.value = converter(n.value);
if (prevNode != null && comparisonFunc(prevNode.value, n.value)) {
n.count += prevNode.count;
UpdateAugmentedData(n);
RemoveNode(prevNode);
}
prevNode = n;
}
}
/// <summary>
/// Inserts the specified <paramref name="item"/> at <paramref name="index"/>
/// </summary>

2
src/Main/Base/Project/Src/Editor/IDocumentBaseVersionProvider.cs

@ -64,6 +64,8 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -64,6 +64,8 @@ namespace ICSharpCode.SharpDevelop.Editor
public struct LineChangeInfo : IEquatable<LineChangeInfo>
{
public static readonly LineChangeInfo Empty = new LineChangeInfo(ChangeType.None, "");
ChangeType change;
public ChangeType Change {

Loading…
Cancel
Save