From 27d20d4daf52f103525b4675af6aa289429abab9 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 18 Dec 2010 14:29:16 +0100 Subject: [PATCH] Remove dictionary from HeightTree. --- .../Document/CollapsingTests.cs | 30 +++++++++---------- .../Document/HeightTests.cs | 2 +- .../Rendering/HeightTree.cs | 23 +++++--------- .../Rendering/TextView.cs | 6 ++-- 4 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/CollapsingTests.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/CollapsingTests.cs index a88c977623..c8ae9d1d4a 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/CollapsingTests.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/CollapsingTests.cs @@ -28,13 +28,13 @@ namespace ICSharpCode.AvalonEdit.Document { CollapsedLineSection sec1 = heightTree.CollapseText(document.GetLineByNumber(from), document.GetLineByNumber(to)); for (int i = 1; i < from; i++) { - Assert.IsFalse(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsFalse(heightTree.GetIsCollapsed(i)); } for (int i = from; i <= to; i++) { - Assert.IsTrue(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsTrue(heightTree.GetIsCollapsed(i)); } for (int i = to + 1; i <= 10; i++) { - Assert.IsFalse(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsFalse(heightTree.GetIsCollapsed(i)); } CheckHeights(); return sec1; @@ -52,7 +52,7 @@ namespace ICSharpCode.AvalonEdit.Document CollapsedLineSection sec1 = heightTree.CollapseText(document.GetLineByNumber(4), document.GetLineByNumber(6)); sec1.Uncollapse(); for (int i = 1; i <= 10; i++) { - Assert.IsFalse(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsFalse(heightTree.GetIsCollapsed(i)); } CheckHeights(); } @@ -65,7 +65,7 @@ namespace ICSharpCode.AvalonEdit.Document try { SimpleCheck(from, to).Uncollapse(); for (int i = 1; i <= 10; i++) { - Assert.IsFalse(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsFalse(heightTree.GetIsCollapsed(i)); } CheckHeights(); } catch { @@ -82,13 +82,13 @@ namespace ICSharpCode.AvalonEdit.Document CollapsedLineSection sec1 = heightTree.CollapseText(document.GetLineByNumber(4), document.GetLineByNumber(6)); document.Insert(document.GetLineByNumber(5).Offset, "a\nb\nc"); for (int i = 1; i < 4; i++) { - Assert.IsFalse(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsFalse(heightTree.GetIsCollapsed(i)); } for (int i = 4; i <= 8; i++) { - Assert.IsTrue(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsTrue(heightTree.GetIsCollapsed(i)); } for (int i = 9; i <= 12; i++) { - Assert.IsFalse(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsFalse(heightTree.GetIsCollapsed(i)); } CheckHeights(); } @@ -101,13 +101,13 @@ namespace ICSharpCode.AvalonEdit.Document int line6Offset = document.GetLineByNumber(6).Offset; document.Remove(line4Offset, line6Offset - line4Offset); for (int i = 1; i < 3; i++) { - Assert.IsFalse(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsFalse(heightTree.GetIsCollapsed(i)); } for (int i = 3; i <= 5; i++) { - Assert.IsTrue(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsTrue(heightTree.GetIsCollapsed(i)); } for (int i = 6; i <= 8; i++) { - Assert.IsFalse(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsFalse(heightTree.GetIsCollapsed(i)); } CheckHeights(); } @@ -120,13 +120,13 @@ namespace ICSharpCode.AvalonEdit.Document int line8Offset = document.GetLineByNumber(8).Offset; document.Remove(line5Offset, line8Offset - line5Offset); for (int i = 1; i < 3; i++) { - Assert.IsFalse(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsFalse(heightTree.GetIsCollapsed(i)); } for (int i = 3; i <= 5; i++) { - Assert.IsTrue(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsTrue(heightTree.GetIsCollapsed(i)); } for (int i = 6; i <= 7; i++) { - Assert.IsFalse(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsFalse(heightTree.GetIsCollapsed(i)); } CheckHeights(); } @@ -138,7 +138,7 @@ namespace ICSharpCode.AvalonEdit.Document int line3Offset = document.GetLineByNumber(3).Offset; document.Remove(line3Offset - 1, 1); for (int i = 1; i <= 9; i++) { - Assert.IsFalse(heightTree.GetIsCollapsed(document.GetLineByNumber(i))); + Assert.IsFalse(heightTree.GetIsCollapsed(i)); } CheckHeights(); Assert.AreSame(null, sec1.Start); diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/HeightTests.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/HeightTests.cs index f983161b06..a12a740508 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/HeightTests.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/HeightTests.cs @@ -62,7 +62,7 @@ namespace ICSharpCode.AvalonEdit.Document internal static void CheckHeights(TextDocument document, HeightTree heightTree) { - double[] heights = document.Lines.Select(l => heightTree.GetIsCollapsed(l) ? 0 : heightTree.GetHeight(l)).ToArray(); + double[] heights = document.Lines.Select(l => heightTree.GetIsCollapsed(l.LineNumber) ? 0 : heightTree.GetHeight(l)).ToArray(); double[] visualPositions = new double[document.LineCount+1]; for (int i = 0; i < heights.Length; i++) { visualPositions[i+1]=visualPositions[i]+heights[i]; diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/HeightTree.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/HeightTree.cs index a5c7958422..3acc90d67d 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/HeightTree.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/HeightTree.cs @@ -17,8 +17,8 @@ namespace ICSharpCode.AvalonEdit.Rendering sealed class HeightTree : ILineTracker, IDisposable { // TODO: Optimize this. This tree takes alot of memory. - // (56 bytes for HeightTreeNode + ca. 25 bytes per node for the dictionary) - // We should try to get rid of the dictionary and find height nodes per index. + // (56 bytes for HeightTreeNode + // We should try to get rid of the dictionary and find height nodes per index. (DONE!) // And we might do much better by compressing lines with the same height into a single node. // That would also improve load times because we would always start with just a single node. @@ -39,7 +39,6 @@ namespace ICSharpCode.AvalonEdit.Rendering #region Constructor readonly TextDocument document; - Dictionary dict; HeightTreeNode root; WeakLineTracker weakLineTracker; @@ -55,7 +54,6 @@ namespace ICSharpCode.AvalonEdit.Rendering { if (weakLineTracker != null) weakLineTracker.Deregister(); - this.dict = null; this.root = null; this.weakLineTracker = null; } @@ -64,7 +62,7 @@ namespace ICSharpCode.AvalonEdit.Rendering HeightTreeNode GetNode(DocumentLine ls) { - return dict[ls]; + return GetNodeByIndex(ls.LineNumber - 1); } #endregion @@ -83,13 +81,10 @@ namespace ICSharpCode.AvalonEdit.Rendering s.End = null; } - dict = new Dictionary((int)(document.LineCount / 0.7)); HeightTreeNode[] nodes = new HeightTreeNode[document.LineCount]; int lineNumber = 0; foreach (DocumentLine ls in document.Lines) { - HeightTreeNode node = new HeightTreeNode(ls, DefaultLineHeight); - dict.Add(ls, node); - nodes[lineNumber++] = node; + nodes[lineNumber++] = new HeightTreeNode(ls, DefaultLineHeight); } Debug.Assert(nodes.Length > 0); // now build the corresponding balanced tree @@ -135,11 +130,11 @@ namespace ICSharpCode.AvalonEdit.Rendering cs.End = null; } else if (cs.Start == line) { Uncollapse(cs); - cs.Start = GetLineByNumber(line.LineNumber + 1); + cs.Start = line.NextLine; AddCollapsedSection(cs, cs.End.LineNumber - cs.Start.LineNumber + 1); } else if (cs.End == line) { Uncollapse(cs); - cs.End = GetLineByNumber(line.LineNumber - 1); + cs.End = line.PreviousLine; AddCollapsedSection(cs, cs.End.LineNumber - cs.Start.LineNumber + 1); } } @@ -149,7 +144,6 @@ namespace ICSharpCode.AvalonEdit.Rendering // clear collapsedSections from removed line: prevent damage if removed line is in "nodesToCheckForMerging" node.lineNode.collapsedSections = null; EndRemoval(); - dict.Remove(line); } // void ILineTracker.AfterRemoveLine(DocumentLine line) @@ -168,7 +162,6 @@ namespace ICSharpCode.AvalonEdit.Rendering HeightTreeNode InsertAfter(HeightTreeNode node, DocumentLine newLine) { HeightTreeNode newNode = new HeightTreeNode(newLine, DefaultLineHeight); - dict.Add(newLine, newNode); if (node.right == null) { if (node.lineNode.collapsedSections != null) { // we are inserting directly after node - so copy all collapsedSections @@ -485,9 +478,9 @@ namespace ICSharpCode.AvalonEdit.Rendering UpdateAfterChildrenChange(node); } - public bool GetIsCollapsed(DocumentLine line) + public bool GetIsCollapsed(int lineNumber) { - var node = GetNode(line); + var node = GetNodeByIndex(lineNumber - 1); return node.lineNode.IsDirectlyCollapsed || GetIsCollapedFromNode(node); } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs index e08b291714..ccfaed5aae 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs @@ -564,7 +564,7 @@ namespace ICSharpCode.AvalonEdit.Rendering TextRunProperties globalTextRunProperties = CreateGlobalTextRunProperties(); VisualLineTextParagraphProperties paragraphProperties = CreateParagraphProperties(globalTextRunProperties); - while (heightTree.GetIsCollapsed(documentLine)) { + while (heightTree.GetIsCollapsed(documentLine.LineNumber)) { documentLine = documentLine.PreviousLine; } @@ -823,7 +823,7 @@ namespace ICSharpCode.AvalonEdit.Rendering IVisualLineTransformer[] lineTransformersArray, Size availableSize) { - if (heightTree.GetIsCollapsed(documentLine)) + if (heightTree.GetIsCollapsed(documentLine.LineNumber)) throw new InvalidOperationException("Trying to build visual line from collapsed line"); Debug.WriteLine("Building line " + documentLine.LineNumber); @@ -839,7 +839,7 @@ namespace ICSharpCode.AvalonEdit.Rendering #if DEBUG for (int i = visualLine.FirstDocumentLine.LineNumber + 1; i <= visualLine.LastDocumentLine.LineNumber; i++) { - if (!heightTree.GetIsCollapsed(document.GetLineByNumber(i))) + if (!heightTree.GetIsCollapsed(i)) throw new InvalidOperationException("Line " + i + " was skipped by a VisualLineElementGenerator, but it is not collapsed."); } #endif