Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorMike Krüger <mkrueger@xamarin.com>2012-06-01 13:58:12 +0400
committerMike Krüger <mkrueger@xamarin.com>2012-06-01 13:58:12 +0400
commita7f6566e54399bc4790ff01741a09388126593e4 (patch)
treee9f61de704d77b22c1568f0173663f1a5a75196b /main
parent99ae3e0355c89022a690daa56875c2b6978e1662 (diff)
[TextEditor] Height tree is now thread safe.
Diffstat (limited to 'main')
-rw-r--r--main/src/core/Mono.Texteditor/Mono.TextEditor/HeightTree.cs412
1 files changed, 214 insertions, 198 deletions
diff --git a/main/src/core/Mono.Texteditor/Mono.TextEditor/HeightTree.cs b/main/src/core/Mono.Texteditor/Mono.TextEditor/HeightTree.cs
index 5f1ce13dbc..107ff9cbd9 100644
--- a/main/src/core/Mono.Texteditor/Mono.TextEditor/HeightTree.cs
+++ b/main/src/core/Mono.Texteditor/Mono.TextEditor/HeightTree.cs
@@ -42,7 +42,6 @@ namespace Mono.TextEditor
// TODO: Add support for line word wrap to the text editor - with the height tree this is possible.
internal RedBlackTree<HeightNode> tree = new RedBlackTree<HeightNode> ();
readonly TextEditorData editor;
- readonly Thread guiThread;
public double TotalHeight {
get {
@@ -58,19 +57,12 @@ namespace Mono.TextEditor
public HeightTree (TextEditorData editor)
{
- guiThread = Thread.CurrentThread;
this.editor = editor;
this.editor.Document.Splitter.LineRemoved += HandleLineRemoved;
this.editor.Document.Splitter.LineInserted += HandleLineInserted;
this.editor.Document.FoldTreeUpdated += HandleFoldTreeUpdated;
}
- void CheckThread ()
- {
- if (guiThread != Thread.CurrentThread)
- throw new InvalidOperationException ("Called from the wrong thread.");
- }
-
void HandleLineInserted (object sender, LineEventArgs e)
{
InsertLine (e.Line.LineNumber);
@@ -97,18 +89,19 @@ namespace Mono.TextEditor
void RemoveLine (int line)
{
- CheckThread ();
- try {
- var node = GetNodeByLine (line);
- if (node == null)
- return;
- if (node.count == 1) {
- tree.Remove (node);
- return;
+ lock (tree) {
+ try {
+ var node = GetNodeByLine (line);
+ if (node == null)
+ return;
+ if (node.count == 1) {
+ tree.Remove (node);
+ return;
+ }
+ node.count--;
+ } finally {
+ OnLineUpdateFrom (new HeightChangedEventArgs (line - 1));
}
- node.count--;
- } finally {
- OnLineUpdateFrom (new HeightChangedEventArgs (line - 1));
}
}
@@ -135,103 +128,108 @@ namespace Mono.TextEditor
void InsertLine (int line)
{
- CheckThread ();
- var newLine = new HeightNode () {
- count = 1,
- height = editor.LineHeight
- };
+ lock (tree) {
+ var newLine = new HeightNode () {
+ count = 1,
+ height = editor.LineHeight
+ };
- try {
- if (line == tree.Root.totalCount + 1) {
- tree.InsertAfter (tree.Root.GetOuterRight (), newLine);
- return;
- }
- var node = GetNodeByLine (line);
- if (node == null)
- return;
- if (node.count == 1) {
- tree.InsertBefore (node, newLine);
- return;
+ try {
+ if (line == tree.Root.totalCount + 1) {
+ tree.InsertAfter (tree.Root.GetOuterRight (), newLine);
+ return;
+ }
+ var node = GetNodeByLine (line);
+ if (node == null)
+ return;
+ if (node.count == 1) {
+ tree.InsertBefore (node, newLine);
+ return;
+ }
+ node.count++;
+ } finally {
+ newLine.UpdateAugmentedData ();
+ OnLineUpdateFrom (new HeightChangedEventArgs (line));
}
- node.count++;
- } finally {
- newLine.UpdateAugmentedData ();
- OnLineUpdateFrom (new HeightChangedEventArgs (line));
}
}
bool rebuild;
public void Rebuild ()
{
- CheckThread ();
- rebuild = true;
- try {
- markers.Clear ();
- tree.Count = 1;
- double h = editor.LineCount * editor.LineHeight;
- tree.Root = new HeightNode () {
- height = h,
- totalHeight = h,
- totalCount = editor.LineCount,
- totalVisibleCount = editor.LineCount,
- count = editor.LineCount
- };
-
- foreach (var extendedTextMarkerLine in editor.Document.LinesWithExtendingTextMarkers) {
- int lineNumber = extendedTextMarkerLine.LineNumber;
- double height = editor.GetLineHeight (extendedTextMarkerLine);
- SetLineHeight (lineNumber, height);
- }
-
- foreach (var segment in editor.Document.FoldedSegments.ToArray ()) {
- int start = editor.OffsetToLineNumber (segment.Offset);
- int end = editor.OffsetToLineNumber (segment.EndOffset);
- segment.Marker = Fold (start, end - start);
+ lock (tree) {
+ rebuild = true;
+ try {
+ markers.Clear ();
+ tree.Count = 1;
+ double h = editor.LineCount * editor.LineHeight;
+ tree.Root = new HeightNode () {
+ height = h,
+ totalHeight = h,
+ totalCount = editor.LineCount,
+ totalVisibleCount = editor.LineCount,
+ count = editor.LineCount
+ };
+
+ foreach (var extendedTextMarkerLine in editor.Document.LinesWithExtendingTextMarkers) {
+ int lineNumber = extendedTextMarkerLine.LineNumber;
+ double height = editor.GetLineHeight (extendedTextMarkerLine);
+ SetLineHeight (lineNumber, height);
+ }
+
+ foreach (var segment in editor.Document.FoldedSegments.ToArray ()) {
+ int start = editor.OffsetToLineNumber (segment.Offset);
+ int end = editor.OffsetToLineNumber (segment.EndOffset);
+ segment.Marker = Fold (start, end - start);
+ }
+ } finally {
+ rebuild = false;
}
- } finally {
- rebuild = false;
}
}
public void SetLineHeight (int lineNumber, double height)
{
- CheckThread ();
- var node = GetNodeByLine (lineNumber);
- if (node == null)
- throw new Exception ("No node for line number " + lineNumber + " found. (maxLine=" + tree.Root.totalCount + ")");
- int nodeStartLine = node.GetLineNumber ();
- int remainingLineCount;
- if (nodeStartLine == lineNumber) {
- remainingLineCount = node.count - 1;
- ChangeHeight (node, 1, height);
- if (remainingLineCount > 0) {
- InsertAfter (node, new HeightNode () {
- count = remainingLineCount,
- height = editor.LineHeight * remainingLineCount,
- foldLevel = node.foldLevel
- });
- }
- } else {
- int newLineCount = lineNumber - nodeStartLine;
- remainingLineCount = node.count - newLineCount - 1;
- if (newLineCount != node.count) {
- double newHeight = editor.LineHeight * newLineCount;
- ChangeHeight (node, newLineCount, newHeight);
- }
-
- var newNode = new HeightNode () {
- count = 1,
- height = height,
- foldLevel = node.foldLevel
- };
- InsertAfter (node, newNode);
-
- if (remainingLineCount > 0) {
- InsertAfter (newNode, new HeightNode () {
- count = remainingLineCount,
- height = editor.LineHeight * remainingLineCount,
+ lock (tree) {
+ var node = GetNodeByLine (lineNumber);
+ if (node == null)
+ throw new Exception ("No node for line number " + lineNumber + " found. (maxLine=" + tree.Root.totalCount + ")");
+ int nodeStartLine = node.GetLineNumber ();
+ int remainingLineCount;
+ if (nodeStartLine == lineNumber) {
+ remainingLineCount = node.count - 1;
+ ChangeHeight (node, 1, height);
+ if (remainingLineCount > 0) {
+ InsertAfter (node, new HeightNode () {
+ count = remainingLineCount,
+ height = editor.LineHeight * remainingLineCount,
+ foldLevel = node.foldLevel
+ }
+ );
+ }
+ } else {
+ int newLineCount = lineNumber - nodeStartLine;
+ remainingLineCount = node.count - newLineCount - 1;
+ if (newLineCount != node.count) {
+ double newHeight = editor.LineHeight * newLineCount;
+ ChangeHeight (node, newLineCount, newHeight);
+ }
+
+ var newNode = new HeightNode () {
+ count = 1,
+ height = height,
foldLevel = node.foldLevel
- });
+ };
+ InsertAfter (node, newNode);
+
+ if (remainingLineCount > 0) {
+ InsertAfter (newNode, new HeightNode () {
+ count = remainingLineCount,
+ height = editor.LineHeight * remainingLineCount,
+ foldLevel = node.foldLevel
+ }
+ );
+ }
}
}
OnLineUpdateFrom (new HeightChangedEventArgs (lineNumber));
@@ -253,97 +251,109 @@ namespace Mono.TextEditor
public FoldMarker Fold (int lineNumber, int count)
{
- CheckThread ();
- GetSingleLineNode (lineNumber);
- lineNumber++;
-
- for (int i = lineNumber; i < lineNumber + count; i++) {
- var node = GetSingleLineNode (i);
- node.foldLevel++;
- node.UpdateAugmentedData ();
+ lock (tree) {
+ GetSingleLineNode (lineNumber);
+ lineNumber++;
+
+ for (int i = lineNumber; i < lineNumber + count; i++) {
+ var node = GetSingleLineNode (i);
+ node.foldLevel++;
+ node.UpdateAugmentedData ();
+ }
+ var result = new FoldMarker (lineNumber, count);
+ markers.Add (result);
+ OnLineUpdateFrom (new HeightChangedEventArgs (lineNumber - 1));
+ return result;
}
- var result = new FoldMarker (lineNumber, count);
- markers.Add (result);
- OnLineUpdateFrom (new HeightChangedEventArgs (lineNumber - 1));
- return result;
}
public void Unfold (FoldMarker marker, int lineNumber, int count)
{
- CheckThread ();
- if (marker == null || !markers.Contains (marker))
- return;
- markers.Remove (marker);
-
- GetSingleLineNode (lineNumber);
- lineNumber++;
- for (int i = lineNumber; i < lineNumber + count; i++) {
- var node = GetSingleLineNode (i);
- node.foldLevel--;
- node.UpdateAugmentedData ();
+ lock (tree) {
+ if (marker == null || !markers.Contains (marker))
+ return;
+ markers.Remove (marker);
+
+ GetSingleLineNode (lineNumber);
+ lineNumber++;
+ for (int i = lineNumber; i < lineNumber + count; i++) {
+ var node = GetSingleLineNode (i);
+ node.foldLevel--;
+ node.UpdateAugmentedData ();
+ }
+ OnLineUpdateFrom (new HeightChangedEventArgs (lineNumber - 1));
}
- OnLineUpdateFrom (new HeightChangedEventArgs (lineNumber - 1));
}
public double LineNumberToY (int lineNumber)
{
- var node = GetSingleLineNode (lineNumber);
- int ln = lineNumber - 1;
- while (ln > 0 && node != null && node.foldLevel > 0) {
- node = GetSingleLineNode (ln--);
- }
- if (ln == 0 || node == null)
- return 0;
- double result = node.Left != null ? ((HeightNode)node.Left).totalHeight : 0;
-
- while (node.parent != null) {
- if (node == node.parent.right) {
- if (node.parent.left != null) {
- result += node.parent.left.totalHeight;
- }
- if (node.parent.foldLevel == 0) {
- result += node.parent.height;
+ lock (tree) {
+ var node = GetSingleLineNode (lineNumber);
+ int ln = lineNumber - 1;
+ while (ln > 0 && node != null && node.foldLevel > 0) {
+ node = GetSingleLineNode (ln--);
+ }
+ if (ln == 0 || node == null)
+ return 0;
+ double result = node.Left != null ? ((HeightNode)node.Left).totalHeight : 0;
+
+ while (node.parent != null) {
+ if (node == node.parent.right) {
+ if (node.parent.left != null) {
+ result += node.parent.left.totalHeight;
+ }
+ if (node.parent.foldLevel == 0) {
+ result += node.parent.height;
+ }
}
+ node = node.parent;
}
- node = node.parent;
+ return result;
}
- return result;
}
public int YToLineNumber (double y)
{
- var node = GetNodeByY (y);
- if (node == null)
- return y < 0 ? DocumentLocation.MinLine + (int)(y / editor.LineHeight) : tree.Root.totalCount + (int)((y - tree.Root.totalHeight) / editor.LineHeight);
- int lineOffset = 0;
- if (node.foldLevel == 0) {
- double delta = y - node.GetY ();
- lineOffset = (int)(node.count * delta / node.height);
+ lock (tree) {
+ var node = GetNodeByY (y);
+ if (node == null)
+ return y < 0 ? DocumentLocation.MinLine + (int)(y / editor.LineHeight) : tree.Root.totalCount + (int)((y - tree.Root.totalHeight) / editor.LineHeight);
+ int lineOffset = 0;
+ if (node.foldLevel == 0) {
+ double delta = y - node.GetY ();
+ lineOffset = (int)(node.count * delta / node.height);
+ }
+ return node.GetLineNumber () + lineOffset;
}
- return node.GetLineNumber () + lineOffset;
}
void InsertAfter (HeightNode node, HeightNode newNode)
{
- if (newNode.count <= 0)
- throw new ArgumentOutOfRangeException ("new node count <= 0.");
- tree.InsertAfter (node, newNode);
- newNode.UpdateAugmentedData ();
+ lock (tree) {
+ if (newNode.count <= 0)
+ throw new ArgumentOutOfRangeException ("new node count <= 0.");
+ tree.InsertAfter (node, newNode);
+ newNode.UpdateAugmentedData ();
+ }
}
void InsertBefore (HeightNode node, HeightNode newNode)
{
- if (newNode.count <= 0)
- throw new ArgumentOutOfRangeException ("new node count <= 0.");
- tree.InsertBefore (node, newNode);
- newNode.UpdateAugmentedData ();
+ lock (tree) {
+ if (newNode.count <= 0)
+ throw new ArgumentOutOfRangeException ("new node count <= 0.");
+ tree.InsertBefore (node, newNode);
+ newNode.UpdateAugmentedData ();
+ }
}
void ChangeHeight (HeightNode node, int newCount, double newHeight)
{
- node.count = newCount;
- node.height = newHeight;
- node.UpdateAugmentedData ();
+ lock (tree) {
+ node.count = newCount;
+ node.height = newHeight;
+ node.UpdateAugmentedData ();
+ }
}
int GetValidLine (int logicalLine)
@@ -357,16 +367,18 @@ namespace Mono.TextEditor
public int LogicalToVisualLine (int logicalLine)
{
- if (logicalLine < DocumentLocation.MinLine)
- return DocumentLocation.MinLine;
- if (logicalLine > tree.Root.totalCount)
- return tree.Root.totalCount + logicalLine - tree.Root.totalCount;
- int line = GetValidLine (logicalLine);
- var node = GetNodeByLine (line);
- if (node == null)
- return tree.Root.totalCount + logicalLine - tree.Root.totalCount;
- int delta = logicalLine - node.GetLineNumber ();
- return node.GetVisibleLineNumber () + delta;
+ lock (tree) {
+ if (logicalLine < DocumentLocation.MinLine)
+ return DocumentLocation.MinLine;
+ if (logicalLine > tree.Root.totalCount)
+ return tree.Root.totalCount + logicalLine - tree.Root.totalCount;
+ int line = GetValidLine (logicalLine);
+ var node = GetNodeByLine (line);
+ if (node == null)
+ return tree.Root.totalCount + logicalLine - tree.Root.totalCount;
+ int delta = logicalLine - node.GetLineNumber ();
+ return node.GetVisibleLineNumber () + delta;
+ }
}
int GetValidVisualLine (int logicalLine)
@@ -380,16 +392,18 @@ namespace Mono.TextEditor
public int VisualToLogicalLine (int visualLineNumber)
{
- if (visualLineNumber < DocumentLocation.MinLine)
- return DocumentLocation.MinLine;
- if (visualLineNumber > tree.Root.totalVisibleCount)
- return tree.Root.totalCount + visualLineNumber - tree.Root.totalVisibleCount;
- int line = GetValidVisualLine (visualLineNumber);
- var node = GetNodeByVisibleLine (line);
- if (node == null)
- return tree.Root.totalCount + visualLineNumber - tree.Root.totalVisibleCount;
- int delta = visualLineNumber - node.GetVisibleLineNumber ();
- return node.GetLineNumber () + delta;
+ lock (tree) {
+ if (visualLineNumber < DocumentLocation.MinLine)
+ return DocumentLocation.MinLine;
+ if (visualLineNumber > tree.Root.totalVisibleCount)
+ return tree.Root.totalCount + visualLineNumber - tree.Root.totalVisibleCount;
+ int line = GetValidVisualLine (visualLineNumber);
+ var node = GetNodeByVisibleLine (line);
+ if (node == null)
+ return tree.Root.totalCount + visualLineNumber - tree.Root.totalVisibleCount;
+ int delta = visualLineNumber - node.GetVisibleLineNumber ();
+ return node.GetLineNumber () + delta;
+ }
}
HeightNode GetSingleLineNode (int lineNumber)
@@ -432,25 +446,27 @@ namespace Mono.TextEditor
public HeightNode GetNodeByLine (int lineNumber)
{
- var node = tree.Root;
- int i = lineNumber - 1;
- while (true) {
- if (node == null)
- return null;
- if (node.left != null && i < node.left.totalCount) {
- node = node.left;
- } else {
- if (node.left != null)
- i -= node.left.totalCount;
- i -= node.count;
- if (i < 0)
- return node;
- node = node.right;
+ lock (tree) {
+ var node = tree.Root;
+ int i = lineNumber - 1;
+ while (true) {
+ if (node == null)
+ return null;
+ if (node.left != null && i < node.left.totalCount) {
+ node = node.left;
+ } else {
+ if (node.left != null)
+ i -= node.left.totalCount;
+ i -= node.count;
+ if (i < 0)
+ return node;
+ node = node.right;
+ }
}
}
}
- public HeightNode GetNodeByVisibleLine (int lineNumber)
+ HeightNode GetNodeByVisibleLine (int lineNumber)
{
var node = tree.Root;
int i = lineNumber - 1;
@@ -471,7 +487,7 @@ namespace Mono.TextEditor
}
}
- public HeightNode GetNodeByY (double y)
+ HeightNode GetNodeByY (double y)
{
var node = tree.Root;
double h = y;