コード例 #1
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public void TraversePreOrder <U>(IHierarchical item, U closureArg, Action <U, T> traverseFn, bool includeDisabled = false)
        {
            SkipTreeNode node;

            if (nodeMap.TryGetValue(item.UniqueId, out node))
            {
                TraversePreOrderCallbackStep(node, closureArg, traverseFn, includeDisabled);
                return;
            }

            SkipTreeNode parent = FindParent(item);

            parent = parent ?? root;
            SkipTreeNode ptr = parent.firstChild;

            while (ptr != null)
            {
                if (IsDescendantOf(ptr.item, item))
                {
                    TraversePreOrderCallbackStep(ptr, closureArg, traverseFn, includeDisabled);
                }

                ptr = ptr.nextSibling;
            }
        }
コード例 #2
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        private void TraverseNodes <U>(U closureArg, IHierarchical item, Action <U, SkipTreeNode> traverseFn, bool includeDisabled)
        {
            SkipTreeNode node;

            if (nodeMap.TryGetValue(item.UniqueId, out node))
            {
                TraverseNodesStep(closureArg, node, traverseFn, includeDisabled);
                return;
            }

            SkipTreeNode parent = FindParent(item);

            parent = parent ?? root;
            SkipTreeNode ptr = parent.firstChild;

            while (ptr != null)
            {
                if (IsDescendantOf(ptr.item, item))
                {
                    TraverseNodesStep(closureArg, ptr, traverseFn, includeDisabled);
                }

                ptr = ptr.nextSibling;
            }
        }
コード例 #3
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        private void TraverseNodesStep <U>(U closureArg, SkipTreeNode startNode, Action <U, SkipTreeNode> traverseFn, bool includeDisabled)
        {
            if (startNode.isDisabled && !includeDisabled)
            {
                return;
            }

            traverseFn(closureArg, startNode);

            if (startNode.firstChild == null)
            {
                return;
            }

            LightStack <SkipTreeNode> stack = LightStack <SkipTreeNode> .Get();

            AddChildrenToLightStack(stack, startNode, includeDisabled);

            while (stack.Count > 0)
            {
                SkipTreeNode current = stack.Pop();
                traverseFn(closureArg, current);
                AddChildrenToLightStack(stack, current, includeDisabled);
            }

            LightStack <SkipTreeNode> .Release(ref stack);
        }
コード例 #4
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public void UpdateItemParent(IHierarchical element)
        {
            T item = GetItem(element);

            if (item != null)
            {
                SkipTreeNode node     = nodeMap[item.UniqueId];
                SkipTreeNode parent   = node.parent;
                SkipTreeNode nodeNext = node.nextSibling;
                SkipTreeNode nodePrev = FindPreviousSibling(node);

                if (nodePrev != null)
                {
                    nodePrev.nextSibling = nodeNext;
                }
                else
                {
                    parent.firstChild = nodeNext;
                }

                parent.childCount--;

                node.parent = null;
                parent      = FindParent(element);
                Insert(parent ?? root, node);
            }
        }
コード例 #5
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public int GetSiblingIndex(T element)
        {
            SkipTreeNode node;

            if (!nodeMap.TryGetValue(element.UniqueId, out node))
            {
                return(-1);
            }

            if (node.parent == null)
            {
                return(-1);
            }

            SkipTreeNode ptr   = node.parent.firstChild;
            int          index = 0;

            while (ptr != node)
            {
                index++;
                ptr = ptr.nextSibling;
            }

            return(node.parent.childCount - index - 1);
        }
コード例 #6
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public void ConditionalTraversePreOrder <U>(IHierarchical start, U closureArg, Func <T, U, bool> traverseFn)
        {
            if (start == null)
            {
                ConditionalTraversePreOrderStep(root, closureArg, traverseFn);
                return;
            }

            SkipTreeNode node;

            if (nodeMap.TryGetValue(start.UniqueId, out node))
            {
                ConditionalTraversePreOrderStep(node, closureArg, traverseFn);
                return;
            }

            SkipTreeNode parent = FindParent(start);

            parent = parent ?? root;
            SkipTreeNode ptr = parent.firstChild;

            while (ptr != null)
            {
                if (IsDescendantOf(ptr.item, start))
                {
                    if (traverseFn(ptr.item, closureArg))
                    {
                        ConditionalTraversePreOrderStep(ptr, closureArg, traverseFn);
                    }
                }

                ptr = ptr.nextSibling;
            }
        }
コード例 #7
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        private void TraversePreOrderCallbackStep(SkipTreeNode startNode, Action <T> traverseFn, bool includeDisabled)
        {
            if (startNode.isDisabled && !includeDisabled)
            {
                return;
            }

            if (startNode != root)
            {
                traverseFn(startNode.item);
            }

            if (startNode.firstChild == null)
            {
                return;
            }

            LightStack <SkipTreeNode> stack = LightStack <SkipTreeNode> .Get();

            AddChildrenToLightStack(stack, startNode, includeDisabled);

            while (stack.Count > 0)
            {
                SkipTreeNode current = stack.Pop();
                traverseFn(current.item);
                AddChildrenToLightStack(stack, current, includeDisabled);
            }

            LightStack <SkipTreeNode> .Release(ref stack);
        }
コード例 #8
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        private void Insert(SkipTreeNode parent, SkipTreeNode inserted)
        {
            SkipTreeNode  ptr     = parent.firstChild;
            IHierarchical element = inserted.item;

            // set parent
            // walk through current parent's children
            // if any of those are descendants of inserted
            // remove from parent
            // attach as first sibling to inserted

            SkipTreeNode insertedLastChild   = null;
            SkipTreeNode parentPreviousChild = null;

            while (ptr != null)
            {
                IHierarchical currentElement = ptr.item;
                if (IsDescendantOf(currentElement, element))
                {
                    SkipTreeNode next = ptr.nextSibling;

                    if (ptr == parent.firstChild)
                    {
                        parent.firstChild = next;
                    }
                    else if (parentPreviousChild != null)
                    {
                        parentPreviousChild.nextSibling = next;
                    }

                    if (insertedLastChild != null)
                    {
                        insertedLastChild.nextSibling = ptr;
                    }
                    else
                    {
                        inserted.firstChild = ptr;
                    }

                    ptr.parent.childCount--;
                    ptr.parent = inserted;
                    inserted.childCount++;
                    ptr.nextSibling   = null;
                    insertedLastChild = ptr;
                    ptr = next;
                }
                else
                {
                    parentPreviousChild = ptr;
                    ptr = ptr.nextSibling;
                }
            }

            parent.childCount++;
            inserted.parent      = parent;
            inserted.isDisabled  = parent.isDisabled;
            inserted.nextSibling = parent.firstChild;
            parent.firstChild    = inserted;
        }
コード例 #9
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public void GetRootItems(IList <T> roots)
        {
            SkipTreeNode ptr = root.firstChild;

            while (ptr != null)
            {
                roots.Add(ptr.item);
                ptr = ptr.nextSibling;
            }
        }
コード例 #10
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public void TraverseRecursePreOrder()
        {
            SkipTreeNode ptr = root.firstChild;

            while (ptr != null)
            {
                TraverseRecursePreorderStep(ptr);
                ptr = ptr.nextSibling;
            }
        }
コード例 #11
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        private static TreeNode GetChildTree(SkipTreeNode node, bool includeDisabled)
        {
            SkipTreeNode ptr   = node.firstChild;
            int          count = 0;

            if (node.childCount == 0)
            {
                return(new TreeNode(node.item, node.isDisabled, TreeNode.EmptyArray));
            }

            if (!includeDisabled)
            {
                while (ptr != null)
                {
                    if (!ptr.isDisabled)
                    {
                        count++;
                    }

                    ptr = ptr.nextSibling;
                }

                if (count == 0)
                {
                    return(new TreeNode(node.item, node.isDisabled, TreeNode.EmptyArray));
                }

                ptr = node.firstChild;
                TreeNode[] children = new TreeNode[count];
                count = 0;
                while (ptr != null)
                {
                    children[count++] = GetChildTree(ptr, false);
                    ptr = ptr.nextSibling;
                }

                ArrayUtil.ReverseInPlace(children);
                return(new TreeNode(node.item, node.isDisabled, children));
            }
            else
            {
                count = 0;
                TreeNode[] children = new TreeNode[node.childCount];
                while (ptr != null)
                {
                    children[count++] = GetChildTree(ptr, false);
                    ptr = ptr.nextSibling;
                }

                ArrayUtil.ReverseInPlace(children);
                return(new TreeNode(node.item, true, children));
            }
        }
コード例 #12
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        private void TraversePreOrderCallbackStep <U>(SkipTreeNode startNode, U closureArg, Action <U, T> traverseFn, bool includeDisabled)
        {
            LightStack <SkipTreeNode> stack = LightStack <SkipTreeNode> .Get();

            AddChildrenToLightStack(stack, startNode, includeDisabled);
            while (stack.Count > 0)
            {
                SkipTreeNode current = stack.Pop();
                traverseFn(closureArg, current.item);
                AddChildrenToLightStack(stack, current, includeDisabled);
            }

            LightStack <SkipTreeNode> .Release(ref stack);
        }
コード例 #13
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        private static void AddChildrenToLightStack(LightStack <SkipTreeNode> stack, SkipTreeNode parent, bool includeDisabled)
        {
            SkipTreeNode ptr = parent.firstChild;

            while (ptr != null)
            {
                if (includeDisabled || !ptr.isDisabled)
                {
                    stack.Push(ptr);
                }

                ptr = ptr.nextSibling;
            }
        }
コード例 #14
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        private void TraverseRecursePreorderStep(SkipTreeNode node)
        {
            if (node.isDisabled)
            {
                return;
            }

            SkipTreeNode ptr = node.firstChild;

            while (ptr != null)
            {
                TraverseRecursePreorderStep(ptr);
                ptr = ptr.nextSibling;
            }
        }
コード例 #15
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        private void ConditionalTraversePreOrderStep <U>(SkipTreeNode node, U closureArg, Func <T, U, bool> traverseFn)
        {
            LightStack <SkipTreeNode> stack = LightStack <SkipTreeNode> .Get();

            AddChildrenToLightStack(stack, node, true);

            while (stack.Count > 0)
            {
                SkipTreeNode current = stack.Pop();
                if (traverseFn(current.item, closureArg))
                {
                    AddChildrenToLightStack(stack, current, true);
                }
            }

            LightStack <SkipTreeNode> .Release(ref stack);
        }
コード例 #16
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public void AddItem(T item)
        {
            SkipTreeNode  node;
            IHierarchical element = item.Element;

            if (nodeMap.TryGetValue(element.UniqueId, out node))
            {
                return;
            }

            node = new SkipTreeNode(item);
            nodeMap[element.UniqueId] = node;
            SkipTreeNode parent = FindParent(element);

            Insert(parent ?? root, node);
            onTreeChanged?.Invoke(TreeChangeType.ItemAdded);
        }
コード例 #17
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public void RemoveItem(IHierarchical item)
        {
            SkipTreeNode  node;
            IHierarchical element = item.Element;

            if (!nodeMap.TryGetValue(element.UniqueId, out node))
            {
                return;
            }

            SkipTreeNode parent    = node.parent;
            SkipTreeNode ptr       = node.firstChild;
            SkipTreeNode nodeNext  = node.nextSibling;
            SkipTreeNode nodePrev  = FindPreviousSibling(node);
            SkipTreeNode lastChild = null;

            parent.childCount--;

            while (ptr != null)
            {
                ptr.parent = node.parent;
                node.parent.childCount++;
                lastChild = ptr;
                ptr       = ptr.nextSibling;
            }

            if (parent.firstChild == node)
            {
                parent.firstChild = node.firstChild;
            }
            else
            {
                nodePrev.nextSibling = node.firstChild;
                if (lastChild != null)
                {
                    lastChild.nextSibling = nodeNext;
                }
            }

            node.parent      = null;
            node.item        = default(T);
            node.nextSibling = null;
            node.firstChild  = null;
            nodeMap.Remove(element.UniqueId);
            onTreeChanged?.Invoke(TreeChangeType.ItemRemoved);
        }
コード例 #18
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public int GetRootItems(ref T[] roots)
        {
            if (roots.Length < root.childCount)
            {
                Array.Resize(ref roots, root.childCount);
            }

            int          i   = 0;
            SkipTreeNode ptr = root.firstChild;

            while (ptr != null)
            {
                roots[i] = ptr.item;
                i++;
                ptr = ptr.nextSibling;
            }

            return(root.childCount);
        }
コード例 #19
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        private void TraversePostOrderCallbackStep(SkipTreeNode startNode, Action <T> traverseFn, bool includeDisabled)
        {
            if (startNode.isDisabled && !includeDisabled)
            {
                return;
            }

            SkipTreeNode ptr = startNode.firstChild;

            while (ptr != null)
            {
                TraversePostOrderCallbackStep(ptr, traverseFn, includeDisabled);
                ptr = ptr.nextSibling;
            }

            if (startNode != root)
            {
                traverseFn(startNode.item);
            }
        }
コード例 #20
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public int GetActiveChildCount(IHierarchical element)
        {
            SkipTreeNode node;

            if (!nodeMap.TryGetValue(element.UniqueId, out node))
            {
                return(0);
            }

            SkipTreeNode ptr   = node.parent.firstChild;
            int          count = 0;

            while (ptr != null)
            {
                count += !ptr.isDisabled ? 1 : 0;
                ptr    = ptr.nextSibling;
            }

            return(count);
        }
コード例 #21
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public TreeNode GetTraversableTree(T item, bool includeDisabled = false)
        {
            SkipTreeNode  node;
            IHierarchical element = item.Element;

            if (!nodeMap.TryGetValue(element.UniqueId, out node))
            {
                SkipTreeNode parent = FindParent(item);
                parent = parent ?? root;
                SkipTreeNode ptr = parent.firstChild;

                while (ptr != null)
                {
                    if (!includeDisabled && ptr.isDisabled)
                    {
                        ptr = ptr.nextSibling;
                        continue;
                    }

                    if (IsDescendantOf(ptr.item, item))
                    {
                        scratchNodeList.Add(ptr);
                    }

                    ptr = ptr.nextSibling;
                }

                TreeNode[] children = scratchNodeList.Count == 0
                    ? TreeNode.EmptyArray
                    : new TreeNode[scratchNodeList.Count];

                for (int i = 0; i < children.Length; i++)
                {
                    children[i] = GetChildTree(scratchNodeList[i], includeDisabled);
                }

                return(new TreeNode(item, false, children));
            }

            return(GetChildTree(node, includeDisabled));
        }
コード例 #22
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        private static SkipTreeNode FindPreviousSibling(SkipTreeNode node)
        {
            SkipTreeNode ptr = node.parent.firstChild;

            if (ptr == node)
            {
                return(null);
            }

            while (ptr != null)
            {
                if (ptr.nextSibling == node)
                {
                    return(ptr);
                }

                ptr = ptr.nextSibling;
            }

            return(null);
        }
コード例 #23
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public IList <T> GetAncestors(T start, IList <T> outputList = null)
        {
            if (outputList == null)
            {
                outputList = ListPool <T> .Get();
            }

            SkipTreeNode node;

            if (!nodeMap.TryGetValue(start.UniqueId, out node))
            {
                return(outputList);
            }

            SkipTreeNode ptr = node.parent;

            while (ptr != null)
            {
                outputList.Add(ptr.item);
                ptr = ptr.parent;
            }

            return(outputList);
        }
コード例 #24
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public void SetSiblingIndex(T element, int index)
        {
            SkipTreeNode node;

            if (!nodeMap.TryGetValue(element.UniqueId, out node))
            {
                return;
            }

            if (node == root)
            {
                return;
            }

            int count = node.parent.childCount;

            if (index > count)
            {
                index = count;
            }

            // whole list is inverted with respect the order in which
            // items are added, we need to adjust indices to fix this
            index = count - 1 - index;


            if (node.parent.firstChild == node)
            {
                if (count > 1)
                {
                    node.parent.firstChild = node.nextSibling;
                }
                else
                {
                    return;
                }
            }
            else
            {
                SkipTreeNode prev = FindPreviousSibling(node);

                if (prev != null)
                {
                    prev.nextSibling = node.nextSibling;
                }
                else
                {
                    node.nextSibling = null;
                }
            }

            if (index <= 0)
            {
                node.nextSibling       = node.parent.firstChild;
                node.parent.firstChild = node;
                return;
            }

            SkipTreeNode trail = null;
            SkipTreeNode ptr   = node.parent.firstChild;
            int          i     = 0;

            while (ptr != null && i < index)
            {
                i++;
                trail = ptr;
                ptr   = ptr.nextSibling;
            }

            if (i == index)
            {
                node.nextSibling = ptr;
                // ReSharper disable once PossibleNullReferenceException
                trail.nextSibling = node;
            }
            else
            {
                Debug.Assert(trail != null, nameof(trail) + " != null");
                trail.nextSibling = node;
            }
        }
コード例 #25
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
        public void RemoveHierarchy(IHierarchical item)
        {
            SkipTreeNode              node;
            IHierarchical             element = item.Element;
            LightStack <SkipTreeNode> stack   = LightStack <SkipTreeNode> .Get();

            SkipTreeNode parent = FindParent(item) ?? root;

            if (!nodeMap.TryGetValue(element.UniqueId, out node))
            {
                SkipTreeNode trail = null;
                SkipTreeNode ptr   = parent.firstChild;
                while (ptr != null)
                {
                    if (IsDescendantOf(ptr.item, item))
                    {
                        if (ptr == parent.firstChild)
                        {
                            parent.firstChild = ptr.nextSibling;
                        }
                        else if (trail != null)
                        {
                            trail.nextSibling = ptr.nextSibling;
                        }

                        stack.Push(ptr);
                    }
                    else
                    {
                        trail = ptr;
                    }

                    ptr = ptr.nextSibling;
                }
            }
            else
            {
                SkipTreeNode nodeNext = node.nextSibling;
                SkipTreeNode nodePrev = FindPreviousSibling(node);

                if (nodePrev != null)
                {
                    nodePrev.nextSibling = nodeNext;
                }
                else if (parent.firstChild == node)
                {
                    parent.firstChild = nodeNext;
                }

                stack.Push(node);
            }

            while (stack.Count > 0)
            {
                SkipTreeNode current = stack.Pop();
                nodeMap.Remove(current.item.UniqueId);
                AddChildrenToLightStack(stack, current, true);
            }

            onTreeChanged?.Invoke(TreeChangeType.HierarchyRemoved);
            LightStack <SkipTreeNode> .Release(ref stack);
        }
コード例 #26
0
ファイル: SkipTree.cs プロジェクト: veboys/UIForia
 public SkipTree()
 {
     root    = new SkipTreeNode(default(T));
     nodeMap = new Dictionary <int, SkipTreeNode>();
 }