/// <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); } } } }
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); }
public static int GetTotalChildrenCount(StratusTreeElement element) { int count = 0; GetTotalChildrenCount(element, ref count); return(count); }
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); }
/// <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(); }
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); }
public static StratusTreeElement[] GetAllChildren(StratusTreeElement element) { List <StratusTreeElement> children = new List <StratusTreeElement>(); GetChildrenRecursive(element, children); return(children.ToArray()); }
private static void GetChildrenRecursive(StratusTreeElement element, List <StratusTreeElement> children) { foreach (var child in element.children) { children.Add(child); GetChildrenRecursive(child, children); } }
public void Repair() { //this.Clear(); if (!this.hasRoot) { this.AddRoot(); } StratusTreeElement.UpdateDepthValues(this.root); }
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); }
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); } }
//------------------------------------------------------------------------/ // 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); } }
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"); }
/// <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); }
/// <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); }
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); }
/// <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); }
/// <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(); }
/// <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(); }
//------------------------------------------------------------------------/ // 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); }
/// <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); }
/// <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(); }
private void BuildRootFromElements() { this._root = StratusTreeElement.ListToTree(this.elements); }
public Exception Validate() { Exception exception = StratusTreeElement.Validate(this.elements); return(exception); }
/// <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()); }
/// <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); }
/// <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]); }
/// <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()); }
//------------------------------------------------------------------------/ // Methods: Public //------------------------------------------------------------------------/ public void Assert() { StratusTreeElement.Assert(this.elements); }