capture static method

CapturedThemes capture({
  1. required BuildContext from,
  2. required BuildContext? to,
})

Returns a CapturedThemes object that includes all the InheritedThemes between the given from and to BuildContexts.

The to context must be an ancestor of the from context. If to is null, all ancestor inherited themes of from up to the root of the widget tree are captured.

After calling this method, the themes present between from and to are frozen in the returned CapturedThemes object. If the themes (or their theme data) change in the original subtree, those changes will not be applied to the themes captured in the CapturedThemes object - unless this method is called again to re-capture the updated themes.

To wrap a Widget in the captured themes, call CapturedThemes.wrap.

This method can be expensive if there are many widgets between from and to (it walks the element tree between those nodes).

Implementation

static CapturedThemes capture({ required BuildContext from, required BuildContext? to }) {

  if (from == to) {
    // Nothing to capture.
    return CapturedThemes._(const <InheritedTheme>[]);
  }

  final List<InheritedTheme> themes = <InheritedTheme>[];
  final Set<Type> themeTypes = <Type>{};
  late bool debugDidFindAncestor;
  assert(() {
    debugDidFindAncestor = to == null;
    return true;
  }());
  from.visitAncestorElements((Element ancestor) {
    if (ancestor == to) {
      assert(() {
        debugDidFindAncestor = true;
        return true;
      }());
      return false;
    }
    if (ancestor case InheritedElement(widget: final InheritedTheme theme)) {
      final Type themeType = theme.runtimeType;
      // Only remember the first theme of any type. This assumes
      // that inherited themes completely shadow ancestors of the
      // same type.
      if (!themeTypes.contains(themeType)) {
        themeTypes.add(themeType);
        themes.add(theme);
      }
    }
    return true;
  });

  assert(debugDidFindAncestor, 'The provided `to` context must be an ancestor of the `from` context.');
  return CapturedThemes._(themes);
}