/// <summary> /// Gets the entry at counter position. /// </summary> /// <param name="start">The start.</param> /// <param name="searchPosition">The search position.</param> /// <param name="cookie">The cookie.</param> /// <param name="preferLeftMost">if set to <c>true</c> prefer left most.</param> /// <returns></returns> TreeTableWithCounterEntry GetEntryAtCounterPosition(ITreeTableCounter start, ITreeTableCounter searchPosition, int cookie, bool preferLeftMost) { int treeNodeCount = GetCount(); //if (searchPosition < 0 || searchPosition >= VisibleCount) if (searchPosition.Compare(GetStartCounterPosition(), cookie) < 0) { throw new ArgumentOutOfRangeException("searchPosition"); } if (searchPosition.Compare(GetCounterTotal(), cookie) > 0) { throw new ArgumentOutOfRangeException("searchPosition", String.Format("{0} out of range {1}", searchPosition, GetCounterTotal())); } if (this.Root == null) { return(null); } else { // find node ITreeTableNode currentNode = this.Root; ITreeTableCounter currentNodePosition = start; return(GetEntryAtCounterPosition(currentNode, start, searchPosition, cookie, preferLeftMost, out currentNodePosition)); } }
TreeTableWithCounterEntry GetEntryAtCounterPosition(ITreeTableNode currentNode, ITreeTableCounter start, ITreeTableCounter searchPosition, int cookie, bool preferLeftMost, out ITreeTableCounter currentNodePosition) { TreeTableWithCounterBranch savedBranch = null; ITreeTableCounter savedPosition = null; currentNodePosition = start; while (!currentNode.IsEntry()) { var branch = (TreeTableWithCounterBranch)currentNode; var leftB = (ITreeTableCounterNode)branch.Left; ITreeTableCounter rightNodePosition = currentNodePosition.Combine(leftB.GetCounterTotal(), cookie); if (searchPosition.Compare(rightNodePosition, cookie) < 0) { currentNode = branch.Left; } else if (preferLeftMost && searchPosition.Compare(currentNodePosition, cookie) == 0) { while (!currentNode.IsEntry()) { branch = (TreeTableWithCounterBranch)currentNode; currentNode = branch.Left; } } else { // When the right node matches the searchPosition, there might be entries // with the same position in the left branch. For example, there might be // several subsequent tokens on a line in a text editor. Each token will // have the same line index. When searching for the first token in a line, // the method will at that time also check the rightmost nodes in the left // branch. // // When preferLeftMost is False, the last token in the line will be returned. // When preferLeftMost is True, the first last token in the line will be returned. // // Note: This only works for "direct hits", that means when the search position // matches the right node's position. If you search for the "greatest counter // smaller or equal than searchPosition", the latest node will be returned no // matter if there were nodes with the same counter before. // // Take the YAmountCounter in a TextEditor for example. If you search // for a YAmount between lines, the last token of the line will be returned. // In the TextBuffer class special consideration is taken into account for // this scenario. A generic solution would be too costly in this method. if (preferLeftMost && searchPosition.Compare(rightNodePosition, cookie) == 0) { ITreeTableCounter currentNode2Position = null; ITreeTableNode currentNode2 = GetEntryAtCounterPosition(branch.Left, currentNodePosition, searchPosition, cookie, preferLeftMost, out currentNode2Position); if (rightNodePosition.Compare(currentNode2Position, cookie) == 0) { currentNode = currentNode2; currentNodePosition = currentNode2Position; } else { currentNodePosition = rightNodePosition; currentNode = branch.Right; } } else { if (savedBranch == null) { savedBranch = branch; savedPosition = currentNodePosition; } currentNodePosition = rightNodePosition; currentNode = branch.Right; } } } // if (preferLeftMost && savedBranch != null) // { // ITreeTableCounter currentNode2Position = null; // ITreeTableNode currentNode2 = GetEntryAtCounterPosition(savedBranch.Left, savedPosition, searchPosition, cookie, preferLeftMost, out currentNode2Position); // if (currentNodePosition.Compare(currentNode2Position, cookie) == 0) // currentNode = currentNode2; // // while (!currentNode.IsEntry()) // { // TreeTableWithCounterBranch branch = (TreeTableWithCounterBranch) currentNode; // currentNode = branch.Left; // } // } return((TreeTableWithCounterEntry)currentNode); }