private static IEnumerable<Node> GetLineage(Node node) { for (; node != null; node = node.Parent) yield return node; }
private IEnumerable<Node> GetSubtree(Node node) { if (node.ChildrenInternal == null || node.ChildrenInternal.Count == 0) { yield return node; yield break; } var nodes = new Queue<Node>(); nodes.Enqueue(node); while (nodes.Count > 0) { var item = nodes.Dequeue(); yield return item; if (item.ChildrenInternal != null) { foreach (var child in item.ChildrenInternal) { nodes.Enqueue(child); } } } }
private static Path<object> MakePath(Node node) { return new AdaptablePath<object>(GetLineage(node).Reverse().Select(x => x.Adaptee)); }
private void UpdateNodeSubTree(Node node) { UpdateNode(node); if (node.Expanded) { foreach (Node child in node.Children) UpdateNodeSubTree(child); } }
/// <summary> /// This method is called after each GetInfo(), which updates a node's ItemInfo based on its Adaptee.</summary> /// <param name="node"></param> /// <remarks>Derived classes may want to further modify the ItemInfo of the node, before it responds to those modifications. /// Override method to do so.</remarks> protected virtual void OnNodeInfoUpdated(Node node) { }
// Remove all chilren as atomic operation private void RemoveChildren(Node node) { var pathsToRemove = new List<Path<object>>(); // copy to List since unbind modifies the item-to-node map foreach (Node child in node.ChildrenInternal) { Unbind(child); pathsToRemove.Add(MakePath(child)); } node.ChildrenInternal.Clear(); try { m_synchronizingSelection = true; m_selectionContext.RemoveRange(pathsToRemove); } finally { m_synchronizingSelection = false; } }
private void UpdateNode(Node node) { if (m_itemView != null) { m_itemView.GetInfo(node.Adaptee, node.ItemInfo); OnNodeInfoUpdated(node); node.ItemInfoChanged(); } if (m_selectionContext != null && !m_synchronizingSelection) { try { m_synchronizingSelection = true; node.IsSelected = m_selectionContext.SelectionContains(MakePath(node)); } finally { m_synchronizingSelection = false; } } }
internal ObservableCollection<Node> CreateChildren(Node treeNodeViewModel) { var result = new ObservableCollection<Node>(); foreach (var child in TreeView.GetChildren(treeNodeViewModel.Adaptee)) { Node node = CreateNode(child, treeNodeViewModel); if(node != null) result.Add(node); } return result; }
private Node CreateNode(object adaptee, Node parent) { var node = m_itemToNodesMap[adaptee].FirstOrDefault(n => n.Parent == parent); if (node != null) return node; node = new Node(adaptee, this, parent); node.IsSelectedChanged += node_IsSelectedChanged; m_itemToNodesMap.Add(adaptee, node); UpdateNode(node); //to-do: make the caller do this. We're not calling UpdateNode on the cached version above. return node; }
private void AddPaths(Node node, List<object> path, HashSet<Path<object>> paths) { if (node.Expanded) { path.Add(node); paths.Add(new AdaptablePath<object>(path)); foreach (Node child in node.Children) AddPaths(child, path, paths); path.RemoveAt(path.Count - 1); } }
private void ExpandPaths(Node node, List<object> path, HashSet<Path<object>> paths) { path.Add(node); if (paths.Contains(new AdaptablePath<object>(path))) { node.Expanded = true; foreach (Node child in node.ChildrenInternal) ExpandPaths(child, path, paths); } path.RemoveAt(path.Count - 1); }
private void RefreshNode(Node node) { // Sync any added/removed children if (node.ChildrenInternal != null) { // get visible paths List<object> path = new List<object>(); HashSet<Path<object>> paths = new HashSet<Path<object>>(); foreach (Node child in node.ChildrenInternal) AddPaths(child, path, paths); // Removes all child nodes efficiently RemoveChildren(node); // Rebuild nodes foreach(object child in TreeView.GetChildren(node.Adaptee)) { InsertObject(child, node.Adaptee, -1); } foreach (Node child in node.ChildrenInternal) ExpandPaths(child, path, paths); } // Update node properties recursively UpdateNodeSubTree(node); }
public Node(object adaptee, TreeViewModel owner, Node parent) : base(adaptee) { m_owner = owner; Parent = parent; }
private void Unbind(Node node) { m_itemToNodeMap.Remove(node.Adaptee); if (node.ChildrenInternal != null) { foreach (Node child in node.ChildrenInternal) Unbind(child); } }
private static void Swap(ref Node node1, ref Node node2) { Node temp = node1; node1 = node2; node2 = temp; }
// Remove all children as atomic operation private void RemoveChildren(Node node) { var pathsToRemove = new HashSet<Path<object>>(); // copy to List since unbind modifies the item-to-node map foreach (Node child in node.ChildrenInternal) { foreach (var item in GetSubtree(child)) { m_itemToNodesMap.Remove(item); pathsToRemove.Add(MakePath(child)); } } node.ChildrenInternal.Clear(); try { m_synchronizingSelection = true; if (m_selectionContext != null) m_selectionContext.RemoveRange(pathsToRemove); } finally { m_synchronizingSelection = false; } }
private static Node GetRoot(Node node) { while (node.Parent != null) node = node.Parent; return node; }
private Node CreateNode(object adaptee, Node parent) { var node = new Node(adaptee, this, parent); node.IsSelectedChanged += new EventHandler(node_IsSelectedChanged); m_itemToNodeMap.Add(adaptee, node); UpdateNode(node); return node; }