// Iterates through TreeViewGridNodes in preorder (parent first, then children), this 'flattens' the tree. private TreeViewGridNode NextNode(TreeViewGridNode node) { // After me is my first child (if it exists) // In the search, we assume that graph nodes have no children. This avoids infinite search. if (!node.IsGraphNode) { var callees = callees; if (callees != null && callees.Count > 0) { return(callees[0]); } } // Otherwise it is my next sibling while (node != null) { var nextSibling = NextSibling(node); if (nextSibling != null) { return(nextSibling); } node = node.Caller; } return(null); }
/// <summary> /// It is assumed that the node oldFlattenedTree[oldIndex] and newFlattenedTree[newIndex] correspond /// to one another (have the same path to root) /// Copies the expandedness of the node 'oldFlattenedTree[oldIndex]' to the new node at /// newFlattenedTree[newIndex], as well as all the state for child node. /// </summary> internal static void CopyExpandedStateForNode(List <TreeViewGridNode> newFlattenedTree, int newIndex, ObservableCollectionEx <TreeViewGridNode> oldFlattenedTree, int oldIndex) { Debug.Assert(newIndex == newFlattenedTree.Count - 1); TreeViewGridNode oldNode = oldFlattenedTree[oldIndex]; if (oldNode.m_isExpanded) { TreeViewGridNode newNode = newFlattenedTree[newIndex]; Debug.Assert(newNode.Name == oldNode.Name); newNode.m_isExpanded = true; if (newNode.HasChildren) { var children = newNode.MakeChildren(); for (int i = 0; i < children.Count; i++) { var newChild = children[i]; newFlattenedTree.Add(newChild); int oldChildIndex = FindChild(oldFlattenedTree, oldNode, oldIndex, newChild.Name); if (oldChildIndex >= 0) { CopyExpandedStateForNode(newFlattenedTree, newFlattenedTree.Count - 1, oldFlattenedTree, oldChildIndex); } } } } }
internal TreeViewGridNode(TreeViewGrid treeView, object data, TreeViewGridNode parent) { m_treeView = treeView; Data = data; m_isExpanded = !HasChildren; m_parent = parent; if (parent != null) { m_depth = parent.m_depth + 1; } }
/// <summary> /// An Unexpanded TreeViewGridNode does not have any children even if the Data (TreeViewGridNode) does /// This routine will make the necessary children (it is part of expanding the node). /// </summary> private List <TreeViewGridNode> MakeChildren() { Debug.Assert(HasChildren); var ret = new List <TreeViewGridNode>(); TreeViewGridNode lastChild = null; foreach (var modelNode in m_treeView.m_controller.Children(Data)) { lastChild = new TreeViewGridNode(m_treeView, modelNode, this); ret.Add(lastChild); } lastChild.m_isLastChild = true; return(ret); }
/// <summary> /// Find the sampleIndex in the 'Callees' list of the parent for 'node' /// </summary> /// <param name="node"></param> /// <returns></returns> private int IndexInParent(TreeViewGridNode node) { // TODO avoid search var callerCallees = DisplayCallees(node.Caller); int i = 0; while (i < callerCallees.Count) { var callee = callerCallees[i]; if (callee == node) { break; } i++; } return(i); }
private TreeViewGridNode NextSibling(TreeViewGridNode node) { var parent = node.Caller; if (parent == null) { return(null); } int nextIndex = IndexInParent(node) + 1; var parentCallees = DisplayCallees(parent); if (nextIndex >= parentCallees.Count) { return(null); } return(parentCallees[nextIndex]); }
private void Select(TreeViewGridNode item) { Grid.SelectedCells.Clear(); Grid.SelectedItem = item; if (item == null) { Debug.Assert(false, "Null item selected:"); return; } Grid.ScrollIntoView(item); // TODO This stuff feels like a hack. At some point review. var row = (DataGridRow)Grid.ItemContainerGenerator.ContainerFromItem(item); if (row != null) { row.MoveFocus( new System.Windows.Input.TraversalRequest(System.Windows.Input.FocusNavigationDirection.Next)); } }
/// <summary> /// Typically the GUI instantiates the TreeViewGrid as part of some XAML. However to do its job that /// object needs to know what data it is operating on. This is what 'SetController' does. By defining /// an object implementing ITreeViewController and passing it to this method, you populate the TreeViewGrid /// with data. /// </summary> public void SetController(ITreeViewController controller) { m_controller = controller; // Set up the columns for (int i = 0; i < m_controller.ColumnNames.Count; i++) { var columnName = m_controller.ColumnNames[i]; var columnIdx = i + 1; // Skip the name column if (columnIdx < Grid.Columns.Count) { var column = Grid.Columns[columnIdx]; column.Header = columnName; column.Visibility = System.Windows.Visibility.Visible; } } List <TreeViewGridNode> newFlattenedTree = new List <TreeViewGridNode>(); newFlattenedTree.Add(new TreeViewGridNode(this, controller.Root, null)); // Copy over the nodes to the new flattened tree (as best we can) if (m_flattenedTree.Count > 0 && m_flattenedTree[0].Name == controller.Name(controller.Root)) { TreeViewGridNode.CopyExpandedStateForNode(newFlattenedTree, 0, m_flattenedTree, 0); } // Destroy old nodes (to save memory because GUI keeps references to them) foreach (var node in m_flattenedTree) { node.Dispose(); } // Update the whole tree with the new tree. m_flattenedTree.ReplaceRange(0, m_flattenedTree.Count, newFlattenedTree); Validate(); // Expand the root element m_flattenedTree[0].IsExpanded = true; }
/// <summary> /// Given a TreeViewGridNode, find a TreeViewGridNode for it (insuring that it is displayed) /// </summary> private TreeViewGridNode InsureVisible(object treeNode) { if (treeNode == null) { return(m_flattenedTree[0]); } throw new NotImplementedException(); TreeViewGridNode caller = InsureVisible(treeNode.Caller); if (caller == null) // should never happen, but we can fall back to giving up. { return(null); } caller.IsExpanded = true; caller.ValidateTree(); int callerPos = caller.MyIndex + 1; while (callerPos < m_flattenedTree.Count) { var child = m_flattenedTree[callerPos]; if (child.m_depth <= caller.m_depth) { break; } if (child.Data == treeNode) { return(child); } callerPos++; } Debug.Assert(false, "Should have found call node"); return(null); }
/// <summary> /// Given a node == flattenedTree[sampleIndex] find the sampleIndex in flattenedTree of a child with Name == 'name' /// </summary> private static int FindChild(ObservableCollectionEx <TreeViewGridNode> flattenedTree, TreeViewGridNode node, int index, string name) { Debug.Assert(flattenedTree[index] == node); int childDepth = node.m_depth + 1; int childIndex = index; for (; ;) { childIndex++; if (childIndex >= flattenedTree.Count) { break; } var child = flattenedTree[childIndex]; if (child.m_depth < childDepth) { break; } if (child.m_depth == childDepth && child.Name == name) { return(childIndex); } } return(-1); }