handleExpandChild method

Future<SchematicLayoutResult?> handleExpandChild(
  1. String nodeId,
  2. String childName
)

Handle expanding a specific child by name for search navigation.

Partially reveals only childName inside nodeId (plus its connecting hyperedges). Used by the search routine to walk the hierarchy without fully expanding every level.

Implementation

Future<SchematicLayoutResult?> handleExpandChild(
  String nodeId,
  String childName,
) async {
  if (isToggling) {
    return null;
  }
  final engine = _layoutEngine;
  if (engine == null || schematicAdapter == null) {
    return null;
  }

  setState(() {
    isToggling = true;
    togglingLabel = 'Expanding...';
    pendingToggleNodeId = nodeId;
  });

  // Let the spinner appear before heavy processing.
  final completer = Completer<void>();
  WidgetsBinding.instance.addPostFrameCallback((_) {
    completer.complete();
  });
  await completer.future;
  SchedulerBinding.instance.ensureVisualUpdate();

  try {
    final expanded = schematicAdapter!.expandChild(nodeId, childName);
    if (!expanded) {
      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;
    }

    setState(() {
      layout = newLayout;
      isToggling = false;
      pendingToggleNodeId = null;
      focusPortId = null;
      recentlyToggledNodeId = nodeId;
    });

    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (mounted) {
        setState(() {
          recentlyToggledNodeId = null;
        });
      }
    });

    return newLayout;
  } on Exception {
    if (mounted) {
      setState(() {
        isToggling = false;
        pendingToggleNodeId = null;
      });
    }
    return null;
  }
}