handleNodeToggleRecursive method
- String nodeId
Recursive version of handleNodeToggle (Shift+click).
Expands/collapses the node and all descendant submodules.
Implementation
Future<SchematicLayoutResult?> handleNodeToggleRecursive(
String nodeId,
) async {
if (isToggling) {
return null;
}
final engine = _layoutEngine;
if (engine == null || schematicAdapter == null) {
return null;
}
// Determine label before the toggle mutates state.
final wasExpanded = schematicAdapter!.isExpanded(nodeId);
final wasPartiallyExpanded =
schematicAdapter!.schematic.nodeMap[nodeId]?.isPartiallyExpanded ??
false;
setState(() {
isToggling = true;
togglingLabel = (wasExpanded && !wasPartiallyExpanded)
? 'Collapsing...'
: 'Expanding...';
pendingToggleNodeId = nodeId;
});
final completer = Completer<void>();
WidgetsBinding.instance.addPostFrameCallback((_) {
completer.complete();
});
await completer.future;
SchedulerBinding.instance.ensureVisualUpdate();
try {
final toggled = schematicAdapter!.toggleNodeRecursive(nodeId);
if (!toggled) {
if (mounted) {
setState(() {
isToggling = false;
pendingToggleNodeId = null;
});
}
return null;
}
final elkGraph = schematicAdapter!.schematic.toJsGraph();
final newLayout = await engine.computeLayoutFromElkGraph(
elkGraph,
sessionId: _sessionId,
);
if (newLayout.hasError || !mounted) {
if (mounted) {
setState(() {
isToggling = false;
pendingToggleNodeId = null;
});
}
return null;
}
// When collapsing, zoom to the parent boundary; when expanding,
setState(() {
layout = newLayout;
isToggling = false;
pendingToggleNodeId = null;
recentlyToggledNodeId = nodeId;
});
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
setState(() {
recentlyToggledNodeId = null;
});
}
});
return newLayout;
} on Exception {
if (mounted) {
setState(() {
isToggling = false;
pendingToggleNodeId = null;
});
}
return null;
}
}