コード例 #1
0
        /// <summary>
        /// Updates the depth values below any given element (after reparenting elements)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="root"></param>
        public static void UpdateDepthValues <T>(T root) where T : StratusTreeElement
        {
            if (root == null)
            {
                throw new ArgumentNullException(nameof(root), "The root is null");
            }

            if (!root.hasChildren)
            {
                return;
            }

            Stack <StratusTreeElement> stack = new Stack <StratusTreeElement>();

            stack.Push(root);
            while (stack.NotEmpty())
            {
                StratusTreeElement current = stack.Pop();
                if (current.hasChildren)
                {
                    foreach (var child in current.children)
                    {
                        child.depth = current.depth + 1;
                        stack.Push(child);
                    }
                }
            }
        }
コード例 #2
0
        public static void TestListToTreeThrowsExceptionIfRootIsInvalidDepth()
        {
            // Arrange
            var list = new List <TestElement>();

            list.Add(new TestElement("root", 0));
            list.Add(new TestElement("A", 1));
            list.Add(new TestElement("B", 1));
            list.Add(new TestElement("Bchild", 2));

            // Test
            bool catchedException = false;

            try
            {
                StratusTreeElement.ListToTree(list);
            }
            catch (Exception)
            {
                catchedException = true;
            }

            // Assert
            Assert.IsTrue(catchedException, "We require the root.depth to be -1, here it is: " + list[0].depth);
        }
コード例 #3
0
        public static int GetTotalChildrenCount(StratusTreeElement element)
        {
            int count = 0;

            GetTotalChildrenCount(element, ref count);
            return(count);
        }
コード例 #4
0
        public static void TestTreeToListWorks()
        {
            // Arrange
            TestElement root = new TestElement("root", -1);

            root.children = new List <StratusTreeElement>();
            root.children.Add(new TestElement("A", 0));
            root.children.Add(new TestElement("B", 0));
            root.children.Add(new TestElement("C", 0));

            root.children[1].children = new List <StratusTreeElement>();
            root.children[1].children.Add(new TestElement("Bchild", 1));

            root.children[1].children[0].children = new List <StratusTreeElement>();
            root.children[1].children[0].children.Add(new TestElement("Bchildchild", 2));

            // Test
            List <TestElement> result = new List <TestElement>();

            StratusTreeElement.TreeToList(root, result);

            // Assert
            string[] namesInCorrectOrder = { "root", "A", "B", "Bchild", "Bchildchild", "C" };
            Assert.AreEqual(namesInCorrectOrder.Length, result.Count, "Result count is not match");
            for (int i = 0; i < namesInCorrectOrder.Length; ++i)
            {
                Assert.AreEqual(namesInCorrectOrder[i], result[i].name);
            }
            StratusTreeElement.Assert(result);
        }
コード例 #5
0
        /// <summary>
        /// Adds the given elements to the tree model
        /// </summary>
        /// <param name="elements"></param>
        /// <param name="parent"></param>
        /// <param name="insertPosition"></param>
        public void AddElements(IList <T> elements, StratusTreeElement parent, int insertPosition)
        {
            if (elements == null)
            {
                throw new ArgumentNullException("elements", "elements is null");
            }
            if (elements.Count == 0)
            {
                throw new ArgumentNullException("elements", "elements Count is 0: nothing to add");
            }
            if (parent == null)
            {
                throw new ArgumentNullException("parent", "parent is null");
            }

            if (parent.children == null)
            {
                parent.children = new List <StratusTreeElement>();
            }

            parent.children.InsertRange(insertPosition, elements.Cast <StratusTreeElement>());
            foreach (var element in elements)
            {
                element.parent = parent;
                element.depth  = parent.depth + 1;
                StratusTreeElement.UpdateDepthValues(element);
            }

            StratusTreeElement.TreeToList(this.root, this.data);

            OnChanged();
        }
コード例 #6
0
        public static void TestTreeModelCanAddElements()
        {
            var root = new StratusTreeElement {
                name = "Root", depth = -1
            };
            var listOfElements = new List <StratusTreeElement>();

            listOfElements.Add(root);

            var model = new TreeModel <StratusTreeElement>(listOfElements);

            model.AddElement(new StratusTreeElement {
                name = "Element"
            }, root, 0);
            model.AddElement(new StratusTreeElement {
                name = "Element " + root.children.Count
            }, root, 0);
            model.AddElement(new StratusTreeElement {
                name = "Element " + root.children.Count
            }, root, 0);
            model.AddElement(new StratusTreeElement {
                name = "Sub Element"
            }, root.children[1], 0);

            // Assert order is correct
            string[] namesInCorrectOrder = { "Root", "Element 2", "Element 1", "Sub Element", "Element" };
            Assert.AreEqual(namesInCorrectOrder.Length, listOfElements.Count, "Result count does not match");
            for (int i = 0; i < namesInCorrectOrder.Length; ++i)
            {
                Assert.AreEqual(namesInCorrectOrder[i], listOfElements[i].name);
            }

            // Assert depths are valid
            StratusTreeElement.Assert(listOfElements);
        }
コード例 #7
0
        public static StratusTreeElement[] GetAllChildren(StratusTreeElement element)
        {
            List <StratusTreeElement> children = new List <StratusTreeElement>();

            GetChildrenRecursive(element, children);
            return(children.ToArray());
        }
コード例 #8
0
 private static void GetChildrenRecursive(StratusTreeElement element, List <StratusTreeElement> children)
 {
     foreach (var child in element.children)
     {
         children.Add(child);
         GetChildrenRecursive(child, children);
     }
 }
コード例 #9
0
        public void Repair()
        {
            //this.Clear();
            if (!this.hasRoot)
            {
                this.AddRoot();
            }

            StratusTreeElement.UpdateDepthValues(this.root);
        }
コード例 #10
0
        public void RemoveElementExcludeChildren(TreeElementType element)
        {
            StratusTreeElement parent = element.parent != null ? element.parent : this.root;

            // Reparent all children first
            if (element.hasChildren)
            {
                this.Reparent(parent, element.children);
            }

            this.elements.Remove(element);
        }
コード例 #11
0
        private static void GetTotalChildrenCount(StratusTreeElement element, ref int count)
        {
            if (!element.hasChildren)
            {
                return;
            }

            count += element.childrenCount;
            foreach (var child in element.children)
            {
                GetTotalChildrenCount(child, ref count);
            }
        }
コード例 #12
0
        //------------------------------------------------------------------------/
        // Methods
        //------------------------------------------------------------------------/
        /// <summary>
        /// Sets the data for this tree model
        /// </summary>
        /// <param name="data"></param>
        public void SetData(IList <T> data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("No input data given!");
            }

            this.data = data;
            if (this.numberOfDataElements > 0)
            {
                this.root  = StratusTreeElement.ListToTree(this.data);
                this.maxID = this.data.Max(d => d.id);
            }
        }
コード例 #13
0
        public static void FindCommonAncestorsWithinListWorks()
        {
            // Arrange
            var list = new List <TestElement>();

            list.Add(new TestElement("root", -1));
            list.Add(new TestElement("A", 0));
            var b0 = new TestElement("B", 0);
            var b1 = new TestElement("Bchild", 1);
            var b2 = new TestElement("Bchildchild", 2);

            list.Add(b0);
            list.Add(b1);
            list.Add(b2);

            var c0 = new TestElement("C", 0);

            list.Add(c0);

            var f0 = new TestElement("F", 0);
            var f1 = new TestElement("Fchild", 1);
            var f2 = new TestElement("Fchildchild", 2);

            list.Add(f0);
            list.Add(f1);
            list.Add(f2);

            // Init tree structure: set children and parent properties
            StratusTreeElement.ListToTree(list);

            // Single element
            TestElement[] input          = { b1 };
            TestElement[] expectedResult = { b1 };
            var           result         = StratusTreeElement.FindCommonAncestorsWithinList(input).ToArray();

            Assert.IsTrue(UnityEditor.ArrayUtility.ArrayEquals(expectedResult, result), "Single input should return single output");

            // Single sub tree
            input          = new[] { b1, b2 };
            expectedResult = new[] { b1 };
            result         = StratusTreeElement.FindCommonAncestorsWithinList(input).ToArray();
            Assert.IsTrue(UnityEditor.ArrayUtility.ArrayEquals(expectedResult, result), "Common ancestor should only be b1 ");

            // Multiple sub trees
            input          = new[] { b0, b2, f0, f2, c0 };
            expectedResult = new[] { b0, f0, c0 };
            result         = StratusTreeElement.FindCommonAncestorsWithinList(input).ToArray();
            Assert.IsTrue(UnityEditor.ArrayUtility.ArrayEquals(expectedResult, result), "Common ancestor should only be b0, f0, c0");
        }
コード例 #14
0
        /// <summary>
        /// Gets the ids of all ancestors to the element of given id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public IList <int> GetAncestors(int id)
        {
            var parents          = new List <int>();
            StratusTreeElement T = Find(id);

            if (T != null)
            {
                while (T.parent != null)
                {
                    parents.Add(T.parent.id);
                    T = T.parent;
                }
            }
            return(parents);
        }
コード例 #15
0
        /// <summary>
        /// Reparents the given elements
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="insertionIndex"></param>
        /// <param name="children"></param>
        public static void Reparent(StratusTreeElement oldParent, StratusTreeElement newParent)
        {
            int depthDifference = oldParent.depth - newParent.depth;

            StratusTreeElement[] children = oldParent.allChildren;

            // Remove draggedItems from their parents
            foreach (var child in children)
            {
                Parent(newParent, child);
                UpdateDepthValues(child);
            }

            if (newParent.children == null)
            {
                newParent.children = new List <StratusTreeElement>();
            }

            // Insert dragged items under new parent
            newParent.children.AddRange(children);
        }
コード例 #16
0
        public static void TestListToTreeWorks()
        {
            // Arrange
            var list = new List <TestElement>();

            list.Add(new TestElement("root", -1));
            list.Add(new TestElement("A", 0));
            list.Add(new TestElement("B", 0));
            list.Add(new TestElement("Bchild", 1));
            list.Add(new TestElement("Bchildchild", 2));
            list.Add(new TestElement("C", 0));

            // Test
            TestElement root = StratusTreeElement.ListToTree(list);

            // Assert
            Assert.AreEqual("root", root.name);
            Assert.AreEqual(3, root.children.Count);
            Assert.AreEqual("C", root.children[2].name);
            Assert.AreEqual("Bchildchild", root.children[1].children[0].children[0].name);
        }
コード例 #17
0
        /// <summary>
        /// Reparents the given elements
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="insertionIndex"></param>
        /// <param name="children"></param>
        public static void Parent(StratusTreeElement parent, StratusTreeElement child)
        {
            // Invalid reparenting input
            if (parent == null)
            {
                return;
            }

            // Remove from old parent
            child.parent.children.Remove(child);
            // Set new parent
            child.parent = parent;
            // Update depth value
            child.depth = parent.depth + 1;
            // Insert the child
            if (parent.children == null)
            {
                parent.children = new List <StratusTreeElement>();
            }
            parent.children.Add(child);
        }
コード例 #18
0
        /// <summary>
        /// Removes the given elements
        /// </summary>
        /// <param name="elements"></param>
        public void RemoveElements(IList <T> elements)
        {
            foreach (var element in elements)
            {
                if (element == this.root)
                {
                    throw new ArgumentException("It is not allowed to remove the root element");
                }
            }

            var commonAncestors = StratusTreeElement.FindCommonAncestorsWithinList(elements);

            foreach (var element in commonAncestors)
            {
                element.parent.children.Remove(element);
                element.parent = null;
            }

            StratusTreeElement.TreeToList(this.root, this.data);

            OnChanged();
        }
コード例 #19
0
        /// <summary>
        /// Reparents the given elements
        /// </summary>
        /// <param name="parentElement"></param>
        /// <param name="insertionIndex"></param>
        /// <param name="elements"></param>
        public void MoveElements(StratusTreeElement parentElement, int insertionIndex, params StratusTreeElement[] elements)
        {
            if (insertionIndex < 0)
            {
                throw new ArgumentException("Invalid input: insertionIndex is -1, client needs to decide what index elements should be reparented at");
            }

            // Invalid reparenting input
            if (parentElement == null)
            {
                return;
            }

            // We are moving items so we adjust the insertion index to accomodate that any items above the insertion index is removed before inserting
            if (insertionIndex > 0)
            {
                insertionIndex -= parentElement.children.GetRange(0, insertionIndex).Count(elements.Contains);
            }

            // Remove draggedItems from their parents
            foreach (var draggedItem in elements)
            {
                draggedItem.parent.children.Remove(draggedItem); // remove from old parent
                draggedItem.parent = parentElement;              // set new parent
            }

            if (parentElement.children == null)
            {
                parentElement.children = new List <StratusTreeElement>();
            }

            // Insert dragged items under new parent
            parentElement.children.InsertRange(insertionIndex, elements);

            StratusTreeElement.UpdateDepthValues(root);
            StratusTreeElement.TreeToList(this.root, this.data);

            OnChanged();
        }
コード例 #20
0
        //------------------------------------------------------------------------/
        // Methods: Private
        //------------------------------------------------------------------------/
        private IList <int> GetParentsBelowStackBased(StratusTreeElement searchFromThis)
        {
            Stack <StratusTreeElement> stack = new Stack <StratusTreeElement>();

            stack.Push(searchFromThis);

            var parentsBelow = new List <int>();

            while (stack.Count > 0)
            {
                StratusTreeElement current = stack.Pop();
                if (current.hasChildren)
                {
                    parentsBelow.Add(current.id);
                    foreach (var T in current.children)
                    {
                        stack.Push(T);
                    }
                }
            }

            return(parentsBelow);
        }
コード例 #21
0
        /// <summary>
        /// Reparents the given elements
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="insertionIndex"></param>
        /// <param name="children"></param>
        public static void Parent(StratusTreeElement parent, params StratusTreeElement[] children)
        {
            // Invalid reparenting input
            if (parent == null)
            {
                return;
            }

            // Remove draggedItems from their parents
            foreach (var child in children)
            {
                Parent(parent, child);
                UpdateDepthValues(child);
            }

            if (parent.children == null)
            {
                parent.children = new List <StratusTreeElement>();
            }

            // Insert dragged items under new parent
            parent.children.AddRange(children);
        }
コード例 #22
0
        /// <summary>
        /// Adds an element onto the tree
        /// </summary>
        /// <param name="element"></param>
        /// <param name="parent"></param>
        /// <param name="insertPosition"></param>
        public void AddElement(T element, StratusTreeElement parent, int insertPosition)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element", "element is null");
            }
            if (parent == null)
            {
                throw new ArgumentNullException("parent", "parent is null");
            }

            if (parent.children == null)
            {
                parent.children = new List <StratusTreeElement>();
            }

            parent.children.Insert(insertPosition, element);
            element.parent = parent;

            StratusTreeElement.UpdateDepthValues(parent);
            StratusTreeElement.TreeToList(this.root, this.data);

            OnChanged();
        }
コード例 #23
0
 private void BuildRootFromElements()
 {
     this._root = StratusTreeElement.ListToTree(this.elements);
 }
コード例 #24
0
        public Exception Validate()
        {
            Exception exception = StratusTreeElement.Validate(this.elements);

            return(exception);
        }
コード例 #25
0
 /// <summary>
 /// Reparents the given elements
 /// </summary>
 /// <param name="parentElement"></param>
 /// <param name="insertionIndex"></param>
 /// <param name="elements"></param>
 public void MoveElements(StratusTreeElement parentElement, int insertionIndex, List <StratusTreeElement> elements)
 {
     MoveElements(parentElement, insertionIndex, elements.ToArray());
 }
コード例 #26
0
 /// <summary>
 /// Reparents the given elements
 /// </summary>
 /// <param name="parentElement"></param>
 /// <param name="insertionIndex"></param>
 /// <param name="elements"></param>
 public void Reparent(StratusTreeElement parentElement, params StratusTreeElement[] elements)
 {
     StratusTreeElement.Parent(parentElement, elements);
 }
コード例 #27
0
        /// <summary>
        /// Returns the root of the tree parsed from the list (always the first element)
        /// Note: The first element is requried to have a depth value of -1, with the rest
        /// of the elements at a depth >= 0
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static T ListToTree <T>(IList <T> list) where T : StratusTreeElement
        {
            // Validate input
            StratusTreeElement.Assert(list);

            // Clear old state
            foreach (var element in list)
            {
                element.parent   = null;
                element.children = null;
            }

            // Set child and parent references using depth info
            for (int parentIndex = 0; parentIndex < list.Count; parentIndex++)
            {
                T parent = list[parentIndex];

                // Been visited before
                bool alreadyHasValidChildren = parent.children != null;
                if (alreadyHasValidChildren)
                {
                    continue;
                }

                // Count children based depth value, lookign at children until its
                // the same depth of this element
                int parentDepth = parent.depth;
                int childCount  = 0;
                for (int i = parentIndex + 1; i < list.Count; i++)
                {
                    int depth = list[i].depth;
                    if (depth == parentDepth + 1)
                    {
                        childCount++;
                    }
                    else if (depth <= parentDepth)
                    {
                        break;
                    }
                }

                // Fill the child array for this element
                List <StratusTreeElement> children = null;
                if (childCount != 0)
                {
                    children   = new List <StratusTreeElement>(childCount);
                    childCount = 0;

                    for (int i = parentIndex + 1; i < list.Count; i++)
                    {
                        int depth = list[i].depth;
                        if (depth == parentDepth + 1)
                        {
                            list[i].parent = parent;
                            children.Add(list[i]);
                            childCount++;
                        }

                        if (depth <= parentDepth)
                        {
                            break;
                        }
                    }
                }

                parent.children = children;
            }

            // Now return the root
            return(list[0]);
        }
コード例 #28
0
 /// <summary>
 /// Reparents the given elements
 /// </summary>
 /// <param name="parentElement"></param>
 /// <param name="insertionIndex"></param>
 /// <param name="elements"></param>
 public void Reparent(StratusTreeElement parentElement, List <StratusTreeElement> elements)
 {
     StratusTreeElement.Parent(parentElement, elements.ToArray());
 }
コード例 #29
0
 //------------------------------------------------------------------------/
 // Methods: Public
 //------------------------------------------------------------------------/
 public void Assert()
 {
     StratusTreeElement.Assert(this.elements);
 }