depthFirstTraversal method

void depthFirstTraversal({
  1. required Visitor<TreeEntry<T>> onTraverse,
  2. ValuePredicate<TreeEntry<T>>? descendCondition,
  3. TreeEntry<T>? rootEntry,
})

Traverses the subtrees of roots creating TreeEntry instances for each visited node.

Every new TreeEntry instance is provided to onTraverse right after it is created, before descending into its subtrees.

descendCondition is used to determine if the descendants of the entry passed to it should be traversed. When not provided, defaults to (TreeEntry<T> entry) => entry.isExpanded.

If rootEntry is provided, its children will be used instead of roots as the roots during traversal. This entry can be used to build a subtree keeping the context of the ancestors in the main tree. This parameter is used by SliverAnimatedTree when animating the expand and collapse operations to animate subtrees in and out of the view without losing indentation context of the main tree.

Implementation

void depthFirstTraversal({
  required Visitor<TreeEntry<T>> onTraverse,
  ValuePredicate<TreeEntry<T>>? descendCondition,
  TreeEntry<T>? rootEntry,
}) {
  final ValuePredicate<TreeEntry<T>> shouldDescend =
      descendCondition ?? defaultDescendCondition;

  int treeIndex = 0;

  void createTreeEntriesRecursively({
    required TreeEntry<T>? parent,
    required Iterable<T> nodes,
    required int level,
  }) {
    TreeEntry<T>? entry;

    for (final T node in nodes) {
      final Iterable<T> children = childrenProvider(node);
      entry = TreeEntry<T>(
        parent: parent,
        node: node,
        index: treeIndex++,
        isExpanded: getExpansionState(node),
        level: level,
        hasChildren: children.isNotEmpty,
      );

      onTraverse(entry);

      if (shouldDescend(entry) && entry.hasChildren) {
        createTreeEntriesRecursively(
          parent: entry,
          nodes: children,
          level: level + 1,
        );
      }
    }

    entry?._hasNextSibling = false;
  }

  if (rootEntry != null) {
    createTreeEntriesRecursively(
      parent: rootEntry,
      nodes: childrenProvider(rootEntry.node),
      level: rootEntry.level + 1,
    );
  } else {
    createTreeEntriesRecursively(
      parent: null,
      nodes: roots,
      level: treeRootLevel,
    );
  }
}