void MergeCollapsedSectionsIfPossible(HeightTreeNode node) { Debug.Assert(node != null); if (inRemoval) { nodesToCheckForMerging.Add(node); return; } // now check if we need to merge collapsedSections together bool merged = false; var collapsedL = node.lineNode.collapsedSections; if (collapsedL != null) { for (int i = collapsedL.Count - 1; i >= 0; i--) { CollapsedLineSection cs = collapsedL[i]; if (cs.Start == node.documentLine || cs.End == node.documentLine) { continue; } if (node.left == null || (node.left.collapsedSections != null && node.left.collapsedSections.Contains(cs))) { if (node.right == null || (node.right.collapsedSections != null && node.right.collapsedSections.Contains(cs))) { // all children of node contain cs: -> merge! if (node.left != null) { node.left.RemoveDirectlyCollapsed(cs); } if (node.right != null) { node.right.RemoveDirectlyCollapsed(cs); } collapsedL.RemoveAt(i); node.AddDirectlyCollapsed(cs); merged = true; } } } if (collapsedL.Count == 0) { node.lineNode.collapsedSections = null; } } if (merged && node.parent != null) { MergeCollapsedSectionsIfPossible(node.parent); } }
HeightTreeNode InsertAfter(HeightTreeNode node, DocumentLine newLine) { HeightTreeNode newNode = new HeightTreeNode(newLine, defaultLineHeight); if (node.right == null) { if (node.lineNode.collapsedSections != null) { // we are inserting directly after node - so copy all collapsedSections // that do not end at node. foreach (CollapsedLineSection cs in node.lineNode.collapsedSections) { if (cs.End != node.documentLine) { newNode.AddDirectlyCollapsed(cs); } } } InsertAsRight(node, newNode); } else { node = node.right.LeftMost; if (node.lineNode.collapsedSections != null) { // we are inserting directly before node - so copy all collapsedSections // that do not start at node. foreach (CollapsedLineSection cs in node.lineNode.collapsedSections) { if (cs.Start != node.documentLine) { newNode.AddDirectlyCollapsed(cs); } } } InsertAsLeft(node, newNode); } return(newNode); }
// node removal: // a node in the middle of the tree is removed as following: // its successor is removed // it is replaced with its successor void BeforeNodeRemove(HeightTreeNode removedNode) { Debug.Assert(removedNode.left == null || removedNode.right == null); var collapsed = removedNode.collapsedSections; if (collapsed != null) { HeightTreeNode childNode = removedNode.left ?? removedNode.right; if (childNode != null) { foreach (CollapsedLineSection cs in collapsed) { childNode.AddDirectlyCollapsed(cs); } } } if (removedNode.parent != null) { MergeCollapsedSectionsIfPossible(removedNode.parent); } }
void MergeCollapsedSectionsIfPossible(HeightTreeNode node) { Debug.Assert(node != null); if (inRemoval) { nodesToCheckForMerging.Add(node); return; } // now check if we need to merge collapsedSections together bool merged = false; var collapsedL = node.lineNode.collapsedSections; if (collapsedL != null) { for (int i = collapsedL.Count - 1; i >= 0; i--) { CollapsedLineSection cs = collapsedL[i]; if (cs.Start == node.documentLine || cs.End == node.documentLine) continue; if (node.left == null || (node.left.collapsedSections != null && node.left.collapsedSections.Contains(cs))) { if (node.right == null || (node.right.collapsedSections != null && node.right.collapsedSections.Contains(cs))) { // all children of node contain cs: -> merge! if (node.left != null) node.left.RemoveDirectlyCollapsed(cs); if (node.right != null) node.right.RemoveDirectlyCollapsed(cs); collapsedL.RemoveAt(i); node.AddDirectlyCollapsed(cs); merged = true; } } } if (collapsedL.Count == 0) node.lineNode.collapsedSections = null; } if (merged && node.parent != null) { MergeCollapsedSectionsIfPossible(node.parent); } }
HeightTreeNode InsertAfter(HeightTreeNode node, DocumentLine newLine) { HeightTreeNode newNode = new HeightTreeNode(newLine, defaultLineHeight); if (node.right == null) { if (node.lineNode.collapsedSections != null) { // we are inserting directly after node - so copy all collapsedSections // that do not end at node. foreach (CollapsedLineSection cs in node.lineNode.collapsedSections) { if (cs.End != node.documentLine) newNode.AddDirectlyCollapsed(cs); } } InsertAsRight(node, newNode); } else { node = node.right.LeftMost; if (node.lineNode.collapsedSections != null) { // we are inserting directly before node - so copy all collapsedSections // that do not start at node. foreach (CollapsedLineSection cs in node.lineNode.collapsedSections) { if (cs.Start != node.documentLine) newNode.AddDirectlyCollapsed(cs); } } InsertAsLeft(node, newNode); } return newNode; }