Skip to content

Commit

Permalink
LookupBoundary (#116429)
Browse files Browse the repository at this point in the history
* LookupBoundary simplified

* tests

* doc and impl complete

* doc fixes

* add more tests

* review

* empty
  • Loading branch information
goderbauer authored Dec 7, 2022
1 parent cc256c3 commit 297f094
Show file tree
Hide file tree
Showing 4 changed files with 1,307 additions and 7 deletions.
38 changes: 31 additions & 7 deletions packages/flutter/lib/src/widgets/framework.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2020,6 +2020,13 @@ class _InactiveElements {
/// this callback.
typedef ElementVisitor = void Function(Element element);

/// Signature for the callback to [BuildContext.visitAncestorElements].
///
/// The argument is the ancestor being visited.
///
/// Return false to stop the walk.
typedef ConditionalElementVisitor = bool Function(Element element);

/// A handle to the location of a widget in the widget tree.
///
/// This class presents a set of methods that can be used from
Expand Down Expand Up @@ -2221,14 +2228,15 @@ abstract class BuildContext {
///
/// All of the qualifications about when [dependOnInheritedWidgetOfExactType] can
/// be called apply to this method as well.
InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object aspect });
InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object? aspect });

/// Obtains the nearest widget of the given type `T`, which must be the type of a
/// concrete [InheritedWidget] subclass, and registers this build context with
/// that widget such that when that widget changes (or a new widget of that
/// type is introduced, or the widget goes away), this build context is
/// rebuilt so that it can obtain new values from that widget.
///
/// {@template flutter.widgets.BuildContext.dependOnInheritedWidgetOfExactType}
/// This is typically called implicitly from `of()` static methods, e.g.
/// [Theme.of].
///
Expand Down Expand Up @@ -2262,13 +2270,15 @@ abstract class BuildContext {
/// [InheritedWidget] subclasses that supports partial updates, like
/// [InheritedModel]. It specifies what "aspect" of the inherited
/// widget this context depends on.
/// {@endtemplate}
T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({ Object? aspect });

/// Obtains the element corresponding to the nearest widget of the given type `T`,
/// which must be the type of a concrete [InheritedWidget] subclass.
///
/// Returns null if no such element is found.
///
/// {@template flutter.widgets.BuildContext.getElementForInheritedWidgetOfExactType}
/// Calling this method is O(1) with a small constant factor.
///
/// This method does not establish a relationship with the target in the way
Expand All @@ -2280,11 +2290,13 @@ abstract class BuildContext {
/// [dependOnInheritedWidgetOfExactType] in [State.didChangeDependencies]. It is
/// safe to use this method from [State.deactivate], which is called whenever
/// the widget is removed from the tree.
/// {@endtemplate}
InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>();

/// Returns the nearest ancestor widget of the given type `T`, which must be the
/// type of a concrete [Widget] subclass.
///
/// {@template flutter.widgets.BuildContext.findAncestorWidgetOfExactType}
/// In general, [dependOnInheritedWidgetOfExactType] is more useful, since
/// inherited widgets will trigger consumers to rebuild when they change. This
/// method is appropriate when used in interaction event handlers (e.g.
Expand All @@ -2306,11 +2318,13 @@ abstract class BuildContext {
///
/// Returns null if a widget of the requested type does not appear in the
/// ancestors of this context.
/// {@endtemplate}
T? findAncestorWidgetOfExactType<T extends Widget>();

/// Returns the [State] object of the nearest ancestor [StatefulWidget] widget
/// that is an instance of the given type `T`.
///
/// {@template flutter.widgets.BuildContext.findAncestorStateOfType}
/// This should not be used from build methods, because the build context will
/// not be rebuilt if the value that would be returned by this method changes.
/// In general, [dependOnInheritedWidgetOfExactType] is more appropriate for such
Expand All @@ -2332,6 +2346,7 @@ abstract class BuildContext {
/// because the widget tree is no longer stable at that time. To refer to
/// an ancestor from one of those methods, save a reference to the ancestor
/// by calling [findAncestorStateOfType] in [State.didChangeDependencies].
/// {@endtemplate}
///
/// {@tool snippet}
///
Expand All @@ -2344,17 +2359,20 @@ abstract class BuildContext {
/// Returns the [State] object of the furthest ancestor [StatefulWidget] widget
/// that is an instance of the given type `T`.
///
/// {@template flutter.widgets.BuildContext.findRootAncestorStateOfType}
/// Functions the same way as [findAncestorStateOfType] but keeps visiting subsequent
/// ancestors until there are none of the type instance of `T` remaining.
/// Then returns the last one found.
///
/// This operation is O(N) as well though N is the entire widget tree rather than
/// a subtree.
/// {@endtemplate}
T? findRootAncestorStateOfType<T extends State>();

/// Returns the [RenderObject] object of the nearest ancestor [RenderObjectWidget] widget
/// that is an instance of the given type `T`.
///
/// {@template flutter.widgets.BuildContext.findAncestorRenderObjectOfType}
/// This should not be used from build methods, because the build context will
/// not be rebuilt if the value that would be returned by this method changes.
/// In general, [dependOnInheritedWidgetOfExactType] is more appropriate for such
Expand All @@ -2371,13 +2389,16 @@ abstract class BuildContext {
/// because the widget tree is no longer stable at that time. To refer to
/// an ancestor from one of those methods, save a reference to the ancestor
/// by calling [findAncestorRenderObjectOfType] in [State.didChangeDependencies].
/// {@endtemplate}
T? findAncestorRenderObjectOfType<T extends RenderObject>();

/// Walks the ancestor chain, starting with the parent of this build context's
/// widget, invoking the argument for each ancestor. The callback is given a
/// reference to the ancestor widget's corresponding [Element] object. The
/// walk stops when it reaches the root widget or when the callback returns
/// false. The callback must not return null.
/// widget, invoking the argument for each ancestor.
///
/// {@template flutter.widgets.BuildContext.visitAncestorElements}
/// The callback is given a reference to the ancestor widget's corresponding
/// [Element] object. The walk stops when it reaches the root widget or when
/// the callback returns false. The callback must not return null.
///
/// This is useful for inspecting the widget tree.
///
Expand All @@ -2387,10 +2408,12 @@ abstract class BuildContext {
/// because the element tree is no longer stable at that time. To refer to
/// an ancestor from one of those methods, save a reference to the ancestor
/// by calling [visitAncestorElements] in [State.didChangeDependencies].
void visitAncestorElements(bool Function(Element element) visitor);
/// {@endtemplate}
void visitAncestorElements(ConditionalElementVisitor visitor);

/// Walks the children of this widget.
///
/// {@template flutter.widgets.BuildContext.visitChildElements}
/// This is useful for applying changes to children after they are built
/// without waiting for the next frame, especially if the children are known,
/// and especially if there is exactly one child (as is always the case for
Expand All @@ -2408,6 +2431,7 @@ abstract class BuildContext {
/// significantly cheaper to use an [InheritedWidget] and have the descendants
/// pull data down, than it is to use [visitChildElements] recursively to push
/// data down to them.
/// {@endtemplate}
void visitChildElements(ElementVisitor visitor);

/// Start bubbling this notification at the given build context.
Expand Down Expand Up @@ -4452,7 +4476,7 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
}

@override
void visitAncestorElements(bool Function(Element element) visitor) {
void visitAncestorElements(ConditionalElementVisitor visitor) {
assert(_debugCheckStateIsActiveForAncestorLookup());
Element? ancestor = _parent;
while (ancestor != null && visitor(ancestor)) {
Expand Down
Loading

0 comments on commit 297f094

Please sign in to comment.