/// <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)); } }
/// <summary> /// Invalidates the counter bottom up. /// </summary> /// <param name="notifyCounterSource">if set to <c>true</c> notify counter source.</param> public override void InvalidateCounterBottomUp(bool notifyCounterSource) { counter = null; if (Parent != null) { Parent.InvalidateCounterBottomUp(notifyCounterSource); } else if (notifyCounterSource) { if (Tree is TreeTableWithCounter) { var tcs = Tree.Tag as ITreeTableCounterSource; if (tcs != null) { tcs.InvalidateCounterBottomUp(); } tcs = ((TreeTableWithCounter)Tree).ParentCounterSource; if (tcs != null) { tcs.InvalidateCounterBottomUp(); } } } }
/// <summary> /// Marks all counters dirty in this node and child nodes. /// </summary> /// <param name="notifyCounterSource">if set to <c>true</c> notify counter source.</param> public void InvalidateCounterTopDown(bool notifyCounterSource) { if (Tree.IsInitializing) { return; } _counter = null; GetLeftC().InvalidateCounterTopDown(notifyCounterSource); GetRightC().InvalidateCounterTopDown(notifyCounterSource); }
/// <summary> /// Marks all summaries dirty in this node and child nodes. /// </summary> /// <param name="notifyCounterSource">if set to <c>true</c> notify counter source.</param> public void InvalidateCounterTopDown(bool notifyCounterSource) { counter = null; if (notifyCounterSource) { ITreeTableCounterSource source = GetCounterSource(); if (notifyCounterSource && source != null) { source.InvalidateCounterTopDown(notifyCounterSource); } } }
/// <summary> /// Returns the total of this node's counter and child nodes. /// </summary> public ITreeTableCounter GetCounterTotal() { if (counter == null) { ITreeTableCounterSource source = GetCounterSource(); if (source != null) { counter = source.GetCounter(); } } return(counter); }
/// <summary> /// Returns the cumulative counter position object of a child node with all counter values. /// </summary> /// <param name="node">The node.</param> /// <returns></returns> public ITreeTableCounter GetCounterPositionOfChild(ITreeTableNode node) { ITreeTableCounter pos = GetCounterPosition(); if (Object.ReferenceEquals(node, Right)) { return(pos.Combine(GetLeftC().GetCounterTotal(), TreeTableCounterCookies.CountAll)); } else if (Object.ReferenceEquals(node, Left)) { return(pos); } throw new ArgumentException("must be a child node", "node"); }
/// <summary> /// Returns the total of this node's counter and child nodes (cached). /// </summary> public ITreeTableCounter GetCounterTotal() { if (Tree.IsInitializing) { return(null); } else if (_counter == null) { ITreeTableCounter left = GetLeftC().GetCounterTotal(); ITreeTableCounter right = GetRightC().GetCounterTotal(); if (left != null && right != null) { _counter = left.Combine(right, TreeTableCounterCookies.CountAll); } } return(_counter); }
double ITreeTableCounter.Compare(ITreeTableCounter other, int cookie) { return(Compare((DistanceLineCounter)other, cookie)); }
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); }
/// <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> /// <returns></returns> TreeTableWithCounterEntry GetEntryAtCounterPosition(ITreeTableCounter start, ITreeTableCounter searchPosition, int cookie) { return(GetEntryAtCounterPosition(start, searchPosition, cookie, false)); }
/// <summary> /// Returns an entry at the specified counter position. A cookie defines the type of counter. /// </summary> /// <param name="searchPosition">The search position.</param> /// <param name="cookie">The cookie.</param> /// <param name="preferLeftMost">Indicates if the leftmost entry should be returned if multiple tree elements have the /// same searchPosition.</param> /// <returns></returns> public TreeTableWithCounterEntry GetEntryAtCounterPosition(ITreeTableCounter searchPosition, int cookie, bool preferLeftMost) { return(GetEntryAtCounterPosition(GetStartCounterPosition(), searchPosition, cookie, preferLeftMost)); }
/// <summary> /// Initializes a new <see cref="TreeTableWithCounter"/>. /// </summary> /// <param name="startPos"></param> /// <param name="sorted"></param> public TreeTableWithCounter(ITreeTableCounter startPos, bool sorted) : base(sorted) { _startPos = startPos; }
/// <summary> /// Reset cached counter. /// </summary> public virtual void InvalidateCounter() { this.counter = null; }
double ITreeTableCounter.Compare(ITreeTableCounter other, int cookie) { return(Compare((TreeTableVisibleCounter)other, cookie)); }
/// <summary> /// Called to combine the values of two counter objects. Results are saved back into this counter object. /// A cookie can filter the operation to a limited set of counter types. /// </summary> /// <param name="x">The x.</param> /// <param name="y">The y.</param> /// <param name="cookie">The cookie.</param> protected virtual void OnCombineCounters(ITreeTableCounter x, ITreeTableCounter y, int cookie) { }
/// <summary> /// Combines one tree object with another and returns the new object. /// </summary> /// <param name="other">The other.</param> /// <param name="cookie">The cookie.</param> /// <returns></returns> ITreeTableCounter ITreeTableCounter.Combine(ITreeTableCounter other, int cookie) { return(Combine((TreeTableVisibleCounter)other, cookie)); }