Esempio n. 1
0
        public int IndexOf(object item)
        {
            SharpTreeNode node = item as SharpTreeNode;

            if (node != null && node.IsVisible && node.GetListRoot() == root)
            {
                if (includeRoot)
                {
                    return(SharpTreeNode.GetVisibleIndexForNode(node));
                }
                else
                {
                    return(SharpTreeNode.GetVisibleIndexForNode(node) - 1);
                }
            }
            else
            {
                return(-1);
            }
        }
Esempio n. 2
0
        internal static int GetVisibleIndexForNode(SharpTreeNode node)
        {
            int index = node.left != null?node.left.GetTotalListLength() : 0;

            while (node.listParent != null)
            {
                if (node == node.listParent.right)
                {
                    if (node.listParent.left != null)
                    {
                        index += node.listParent.left.GetTotalListLength();
                    }
                    if (node.listParent.isVisible)
                    {
                        index++;
                    }
                }
                node = node.listParent;
            }
            return(index);
        }
Esempio n. 3
0
 /// <summary>
 /// Balances the subtree rooted in <paramref name="node"/> and recomputes the 'height' field.
 /// This method assumes that the children of this node are already balanced and have an up-to-date 'height' value.
 /// </summary>
 /// <returns>The new root node</returns>
 static SharpTreeNode Rebalance(SharpTreeNode node)
 {
     Debug.Assert(node.left == null || Math.Abs(node.left.Balance) <= 1);
     Debug.Assert(node.right == null || Math.Abs(node.right.Balance) <= 1);
     // Keep looping until it's balanced. Not sure if this is stricly required; this is based on
     // the Rope code where node merging made this necessary.
     while (Math.Abs(node.Balance) > 1)
     {
         // AVL balancing
         // note: because we don't care about the identity of concat nodes, this works a little different than usual
         // tree rotations: in our implementation, the "this" node will stay at the top, only its children are rearranged
         if (node.Balance > 1)
         {
             if (node.right.Balance < 0)
             {
                 node.right = node.right.RotateRight();
             }
             node = node.RotateLeft();
             // If 'node' was unbalanced by more than 2, we've shifted some of the inbalance to the left node; so rebalance that.
             node.left = Rebalance(node.left);
         }
         else if (node.Balance < -1)
         {
             if (node.left.Balance > 0)
             {
                 node.left = node.left.RotateLeft();
             }
             node = node.RotateRight();
             // If 'node' was unbalanced by more than 2, we've shifted some of the inbalance to the right node; so rebalance that.
             node.right = Rebalance(node.right);
         }
     }
     Debug.Assert(Math.Abs(node.Balance) <= 1);
     node.height          = (byte)(1 + Math.Max(Height(node.left), Height(node.right)));
     node.totalListLength = -1; // mark for recalculation
                                // since balancing checks the whole tree up to the root, the whole path will get marked as invalid
     return(node);
 }
Esempio n. 4
0
 static void InsertNodeAfter(SharpTreeNode pos, SharpTreeNode newNode)
 {
     // newNode might be the model root of a whole subtree, so go to the list root of that subtree:
     newNode = newNode.GetListRoot();
     if (pos.right == null)
     {
         pos.right          = newNode;
         newNode.listParent = pos;
     }
     else
     {
         // insert before pos.right's leftmost:
         pos = pos.right;
         while (pos.left != null)
         {
             pos = pos.left;
         }
         Debug.Assert(pos.left == null);
         pos.left           = newNode;
         newNode.listParent = pos;
     }
     RebalanceUntilRoot(pos);
 }
Esempio n. 5
0
 SharpTreeNode Successor()
 {
     if (right != null)
     {
         SharpTreeNode node = right;
         while (node.left != null)
         {
             node = node.left;
         }
         return(node);
     }
     else
     {
         SharpTreeNode node = this;
         SharpTreeNode oldNode;
         do
         {
             oldNode = node;
             node    = node.listParent;
             // loop while we are on the way up from the right part
         } while (node != null && node.right == oldNode);
         return(node);
     }
 }
Esempio n. 6
0
        SharpTreeNode RotateRight()
        {
            /* Rotate tree to the right
             *
             *       this             left
             *       /  \             /  \
             *     left  C   ===>    A   this
             *     / \                   /  \
             *    A   B                 B    C
             */
            SharpTreeNode b      = left.right;
            SharpTreeNode newTop = left;

            if (b != null)
            {
                b.listParent = this;
            }
            this.left         = b;
            newTop.right      = this;
            newTop.listParent = this.listParent;
            this.listParent   = newTop;
            newTop.right      = Rebalance(this);
            return(newTop);
        }
Esempio n. 7
0
 static void DumpTree(SharpTreeNode node)
 {
     node.GetListRoot().DumpTree();
 }
Esempio n. 8
0
 static int Height(SharpTreeNode node)
 {
     return(node != null ? node.height : 0);
 }
Esempio n. 9
0
        internal protected virtual void OnChildrenChanged(NotifyCollectionChangedEventArgs e)
        {
            if (e.OldItems != null)
            {
                foreach (SharpTreeNode node in e.OldItems)
                {
                    Debug.Assert(node.modelParent == this);
                    node.modelParent = null;
                    Debug.WriteLine("Removing {0} from {1}", node, this);
                    SharpTreeNode removeEnd = node;
                    while (removeEnd.modelChildren != null && removeEnd.modelChildren.Count > 0)
                    {
                        removeEnd = removeEnd.modelChildren.Last();
                    }

                    List <SharpTreeNode> removedNodes = null;
                    int visibleIndexOfRemoval         = 0;
                    if (node.isVisible)
                    {
                        visibleIndexOfRemoval = GetVisibleIndexForNode(node);
                        removedNodes          = node.VisibleDescendantsAndSelf().ToList();
                    }

                    RemoveNodes(node, removeEnd);

                    if (removedNodes != null)
                    {
                        var flattener = GetListRoot().treeFlattener;
                        if (flattener != null)
                        {
                            flattener.NodesRemoved(visibleIndexOfRemoval, removedNodes);
                        }
                    }
                }
            }
            if (e.NewItems != null)
            {
                SharpTreeNode insertionPos;
                if (e.NewStartingIndex == 0)
                {
                    insertionPos = null;
                }
                else
                {
                    insertionPos = modelChildren[e.NewStartingIndex - 1];
                }

                foreach (SharpTreeNode node in e.NewItems)
                {
                    Debug.Assert(node.modelParent == null);
                    node.modelParent = this;
                    node.UpdateIsVisible(isVisible && isExpanded, false);
                    //Debug.WriteLine("Inserting {0} after {1}", node, insertionPos);

                    while (insertionPos != null && insertionPos.modelChildren != null && insertionPos.modelChildren.Count > 0)
                    {
                        insertionPos = insertionPos.modelChildren.Last();
                    }
                    InsertNodeAfter(insertionPos ?? this, node);

                    insertionPos = node;
                    if (node.isVisible)
                    {
                        var flattener = GetListRoot().treeFlattener;
                        if (flattener != null)
                        {
                            flattener.NodesInserted(GetVisibleIndexForNode(node), node.VisibleDescendantsAndSelf());
                        }
                    }
                }
            }

            RaisePropertyChanged("ShowExpander");
            RaiseIsLastChangedIfNeeded(e);
        }