/// <summary> /// Reparents the given elements /// </summary> /// <param name="parentElement"></param> /// <param name="insertionIndex"></param> /// <param name="elements"></param> public void MoveElements(TreeElement parentElement, int insertionIndex, params TreeElement[] 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 <TreeElement>(); } // Insert dragged items under new parent parentElement.children.InsertRange(insertionIndex, elements); TreeElement.UpdateDepthValues(root); TreeElement.TreeToList(this.root, this.data); OnChanged(); }
/// <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 = TreeElement.FindCommonAncestorsWithinList(elements); foreach (var element in commonAncestors) { element.parent.children.Remove(element); element.parent = null; } TreeElement.TreeToList(this.root, this.data); OnChanged(); }
/// <summary> /// Reparents the given elements /// </summary> /// <param name="parent"></param> /// <param name="insertionIndex"></param> /// <param name="children"></param> public static void Parent(TreeElement parent, params TreeElement[] 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 <TreeElement>(); } // Insert dragged items under new parent parent.children.AddRange(children); }
//------------------------------------------------------------------------/ // Methods: Private //------------------------------------------------------------------------/ private IList <int> GetParentsBelowStackBased(TreeElement searchFromThis) { Stack <TreeElement> stack = new Stack <TreeElement>(); stack.Push(searchFromThis); var parentsBelow = new List <int>(); while (stack.Count > 0) { TreeElement current = stack.Pop(); if (current.hasChildren) { parentsBelow.Add(current.id); foreach (var T in current.children) { stack.Push(T); } } } return(parentsBelow); }
public static void TestTreeModelCanRemoveElements() { var root = new TreeElement { name = "Root", depth = -1 }; var listOfElements = new List <TreeElement>(); listOfElements.Add(root); var model = new TreeModel <TreeElement>(listOfElements); model.AddElement(new TreeElement { name = "Element" }, root, 0); model.AddElement(new TreeElement { name = "Element " + root.children.Count }, root, 0); model.AddElement(new TreeElement { name = "Element " + root.children.Count }, root, 0); model.AddElement(new TreeElement { name = "Sub Element" }, root.children[1], 0); model.RemoveElements(new[] { root.children[1].children[0], root.children[1] }); // Assert order is correct string[] namesInCorrectOrder = { "Root", "Element 2", "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 TreeElement.Assert(listOfElements); }
/// <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, TreeElement 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 <TreeElement>(); } parent.children.Insert(insertPosition, element); element.parent = parent; TreeElement.UpdateDepthValues(parent); TreeElement.TreeToList(this.root, this.data); OnChanged(); }
/// <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 : TreeElement { // Validate input TreeElement.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 <TreeElement> children = null; if (childCount != 0) { children = new List <TreeElement>(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]); }
private void Parse() { _root = TreeElement.ListToTree(this.elements); }
/// <summary> /// Reparents the given elements /// </summary> /// <param name="parentElement"></param> /// <param name="insertionIndex"></param> /// <param name="elements"></param> public void Reparent(TreeElement parentElement, List <TreeElement> elements) { TreeElement.Parent(parentElement, elements.ToArray()); }
/// <summary> /// Reparents the given elements /// </summary> /// <param name="parentElement"></param> /// <param name="insertionIndex"></param> /// <param name="elements"></param> public void Reparent(TreeElement parentElement, params TreeElement[] elements) { TreeElement.Parent(parentElement, elements); }
public Exception Validate() { Exception exception = TreeElement.Validate(this.elements); return(exception); }
//------------------------------------------------------------------------/ // Methods: Public //------------------------------------------------------------------------/ public void Assert() { TreeElement.Assert(this.elements); }
/// <summary> /// Reparents the given elements /// </summary> /// <param name="parentElement"></param> /// <param name="insertionIndex"></param> /// <param name="elements"></param> public void MoveElements(TreeElement parentElement, int insertionIndex, List <TreeElement> elements) { MoveElements(parentElement, insertionIndex, elements.ToArray()); }