depthFirstTraversal method
- required Visitor<
TreeEntry< onTraverse,T> > - DescendCondition<
TreeEntry< ? descendCondition,T> > - 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,
DescendCondition<TreeEntry<T>>? descendCondition,
TreeEntry<T>? rootEntry,
}) {
final DescendCondition<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,
);
}
}