dispatchEvent method Null safety

  1. @override
void dispatchEvent(
  1. PointerEvent event,
  2. HitTestResult result
)
override

Handler for device events caught by the binding in live test mode.

Implementation

@override
void dispatchEvent(PointerEvent event, HitTestResult result) {
  if (event is PointerDownEvent) {
    final RenderObject innerTarget = result.path
      .map((HitTestEntry candidate) => candidate.target)
      .whereType<RenderObject>()
      .first;
    final Element? innerTargetElement = _lastWhereOrNull(
      collectAllElementsFrom(binding.renderViewElement!, skipOffstage: true),
      (Element element) => element.renderObject == innerTarget,
    );
    if (innerTargetElement == null) {
      printToConsole('No widgets found at ${event.position}.');
      return;
    }
    final List<Element> candidates = <Element>[];
    innerTargetElement.visitAncestorElements((Element element) {
      candidates.add(element);
      return true;
    });
    assert(candidates.isNotEmpty);
    String? descendantText;
    int numberOfWithTexts = 0;
    int numberOfTypes = 0;
    int totalNumber = 0;
    printToConsole('Some possible finders for the widgets at ${event.position}:');
    for (final Element element in candidates) {
      if (totalNumber > 13) // an arbitrary number of finders that feels useful without being overwhelming
        break;
      totalNumber += 1; // optimistically assume we'll be able to describe it

      final Widget widget = element.widget;
      if (widget is Tooltip) {
        final Iterable<Element> matches = find.byTooltip(widget.message).evaluate();
        if (matches.length == 1) {
          printToConsole("  find.byTooltip('${widget.message}')");
          continue;
        }
      }

      if (widget is Text) {
        assert(descendantText == null);
        assert(widget.data != null || widget.textSpan != null);
        final String text = widget.data ?? widget.textSpan!.toPlainText();
        final Iterable<Element> matches = find.text(text).evaluate();
        descendantText = widget.data;
        if (matches.length == 1) {
          printToConsole("  find.text('$text')");
          continue;
        }
      }

      final Key? key = widget.key;
      if (key is ValueKey<dynamic>) {
        String? keyLabel;
        if (key is ValueKey<int> ||
            key is ValueKey<double> ||
            key is ValueKey<bool>) {
          keyLabel = 'const ${key.runtimeType}(${key.value})';
        } else if (key is ValueKey<String>) {
          keyLabel = "const Key('${key.value}')";
        }
        if (keyLabel != null) {
          final Iterable<Element> matches = find.byKey(key).evaluate();
          if (matches.length == 1) {
            printToConsole('  find.byKey($keyLabel)');
            continue;
          }
        }
      }

      if (!_isPrivate(widget.runtimeType)) {
        if (numberOfTypes < 5) {
          final Iterable<Element> matches = find.byType(widget.runtimeType).evaluate();
          if (matches.length == 1) {
            printToConsole('  find.byType(${widget.runtimeType})');
            numberOfTypes += 1;
            continue;
          }
        }

        if (descendantText != null && numberOfWithTexts < 5) {
          final Iterable<Element> matches = find.widgetWithText(widget.runtimeType, descendantText).evaluate();
          if (matches.length == 1) {
            printToConsole("  find.widgetWithText(${widget.runtimeType}, '$descendantText')");
            numberOfWithTexts += 1;
            continue;
          }
        }
      }

      if (!_isPrivate(element.runtimeType)) {
        final Iterable<Element> matches = find.byElementType(element.runtimeType).evaluate();
        if (matches.length == 1) {
          printToConsole('  find.byElementType(${element.runtimeType})');
          continue;
        }
      }

      totalNumber -= 1; // if we got here, we didn't actually find something to say about it
    }
    if (totalNumber == 0)
      printToConsole('  <could not come up with any unique finders>');
  }
}