Skip to content

Commit

Permalink
Soften layer breakage (#42953)
Browse files Browse the repository at this point in the history
* Replace hard break of Layer.find/All with findAllAnnotations
* Deprecate findAll
  • Loading branch information
dkwingsmt committed Oct 18, 2019
1 parent 124dc66 commit 1c535de
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 127 deletions.
2 changes: 1 addition & 1 deletion packages/flutter/lib/src/gestures/mouse_tracking.dart
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class MouseTracker extends ChangeNotifier {
///
/// The second parameter is a function with which the [MouseTracker] can
/// search for [MouseTrackerAnnotation]s at a given position.
/// Usually it is [Layer.findAll] of the root layer.
/// Usually it is [Layer.findAllAnnotations] of the root layer.
///
/// All of the parameters must not be null.
MouseTracker(this._router, this.annotationFinder)
Expand Down
90 changes: 65 additions & 25 deletions packages/flutter/lib/src/rendering/layer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ import 'debug.dart';
///
/// See also:
///
/// * [Layer.find], [Layer.findAll], and [Layer.findAnnotations], which create
/// and use objects of this class.
/// * [Layer.findAnnotations], which create and use objects of this class.
@immutable
class AnnotationEntry<T> {
/// Create an entry of found annotation by providing the oject and related
Expand Down Expand Up @@ -48,8 +47,8 @@ class AnnotationEntry<T> {
/// See also:
///
/// * [AnnotationEntry], which are members of this class.
/// * [Layer.findAll], and [Layer.findAnnotations], which create and use an
/// object of this class.
/// * [Layer.findAllAnnotations], and [Layer.findAnnotations], which create and
/// use an object of this class.
class AnnotationResult<T> {
final List<AnnotationEntry<T>> _entries = <AnnotationEntry<T>>[];

Expand Down Expand Up @@ -280,23 +279,28 @@ abstract class Layer extends AbstractNode with DiagnosticableTreeMixin {
/// location described by `localPosition`.
///
/// This method is called by the default implementation of [find] and
/// [findAll]. Override this method to customize how the layer should search
/// for annotations, or if the layer has its own annotations to add.
/// [findAllAnnotations]. Override this method to customize how the layer
/// should search for annotations, or if the layer has its own annotations to
/// add.
///
/// The default implementation simply returns `false`, which means neither
/// the layer nor its children has annotations, and the annotation search
/// is not absorbed either (see below for explanation).
///
/// ## About layer annotations
///
/// {@template flutter.rendering.layer.findAnnotations.aboutAnnotations}
/// Annotation is an optional object of any type that can be carried with a
/// An annotation is an optional object of any type that can be carried with a
/// layer. An annotation can be found at a location as long as the owner layer
/// contains the location and is walked to.
///
/// The annotations are searched by first visitng each child recursively, then
/// this layer, resulting in an order from visually front to back. Annotations
/// must meet the given restrictions, such as type and position.
/// The annotations are searched by first visiting each child recursively,
/// then this layer, resulting in an order from visually front to back.
/// Annotations must meet the given restrictions, such as type and position.
///
/// The common way for a value to be found here is by pushing an
/// [AnnotatedRegionLayer] into the layer tree, or by adding the desired
/// annotation by overriding `findAnnotations`.
/// annotation by overriding [findAnnotations].
/// {@endtemplate}
///
/// ## Parameters and return value
Expand Down Expand Up @@ -326,30 +330,64 @@ abstract class Layer extends AbstractNode with DiagnosticableTreeMixin {
AnnotationResult<S> result,
Offset localPosition, {
@required bool onlyFirst,
});
}) {
return false;
}

/// Search this layer and its subtree for the first annotation of type `S`
/// under the point described by `localPosition`.
///
/// Returns null if no matching annotations are found.
///
/// By default this method simply calls [findAnnotations] with `onlyFirst:
/// true` and returns the first result. It is encouraged to override
/// [findAnnotations] instead of this method.
/// true` and returns the annotation of the first result. Prefer overriding
/// [findAnnotations] instead of this method, because during an annotation
/// search, only [findAnnotations] is recursively called, while custom
/// behavior in this method is ignored.
///
/// ## About layer annotations
///
/// {@macro flutter.rendering.layer.findAnnotations.aboutAnnotations}
///
/// See also:
///
/// * [findAll], which is similar but returns all annotations found at the
/// given position.
/// * [findAllAnnotations], which is similar but returns all annotations found
/// at the given position.
/// * [AnnotatedRegionLayer], for placing values in the layer tree.
AnnotationEntry<S> find<S>(Offset localPosition) {
S find<S>(Offset localPosition) {
final AnnotationResult<S> result = AnnotationResult<S>();
findAnnotations<S>(result, localPosition, onlyFirst: true);
return result.entries.isEmpty ? null : result.entries.first;
return result.entries.isEmpty ? null : result.entries.first.annotation;
}

/// Search this layer and its subtree for all annotations of type `S` under
/// the point described by `localPosition`.
///
/// Returns a result with empty entries if no matching annotations are found.
///
/// By default this method simply calls [findAnnotations] with `onlyFirst:
/// false` and returns the annotations of its result. Prefer overriding
/// [findAnnotations] instead of this method, because during an annotation
/// search, only [findAnnotations] is recursively called, while custom
/// behavior in this method is ignored.
///
/// ## About layer annotations
///
/// {@macro flutter.rendering.layer.findAnnotations.aboutAnnotations}
///
/// See also:
///
/// * [find], which is similar but returns the first annotation found at the
/// given position.
/// * [findAllAnnotations], which is similar but returns an
/// [AnnotationResult], which contains more information, such as the local
/// position of the event related to each annotation, and is equally fast,
/// hence is preferred over [findAll].
/// * [AnnotatedRegionLayer], for placing values in the layer tree.
@Deprecated('Use findAllAnnotations instead. This API will be removed in early 2020.')
Iterable<S> findAll<S>(Offset localPosition) {
final AnnotationResult<S> result = findAllAnnotations(localPosition);
return result.entries.map((AnnotationEntry<S> entry) => entry.annotation);
}

/// Search this layer and its subtree for all annotations of type `S` under
Expand All @@ -358,8 +396,10 @@ abstract class Layer extends AbstractNode with DiagnosticableTreeMixin {
/// Returns a result with empty entries if no matching annotations are found.
///
/// By default this method simply calls [findAnnotations] with `onlyFirst:
/// false` and returns its result. It is encouraged to override
/// [findAnnotations] instead of this method.
/// false` and returns the annotations of its result. Prefer overriding
/// [findAnnotations] instead of this method, because during an annotation
/// search, only [findAnnotations] is recursively called, while custom
/// behavior in this method is ignored.
///
/// ## About layer annotations
///
Expand All @@ -370,7 +410,7 @@ abstract class Layer extends AbstractNode with DiagnosticableTreeMixin {
/// * [find], which is similar but returns the first annotation found at the
/// given position.
/// * [AnnotatedRegionLayer], for placing values in the layer tree.
AnnotationResult<S> findAll<S>(Offset localPosition) {
AnnotationResult<S> findAllAnnotations<S>(Offset localPosition) {
final AnnotationResult<S> result = AnnotationResult<S>();
findAnnotations<S>(result, localPosition, onlyFirst: false);
return result;
Expand Down Expand Up @@ -2247,10 +2287,10 @@ class FollowerLayer extends ContainerLayer {
/// layer to the tree is the common way of adding an annotation.
///
/// An annotation is an optional object of any type that, when attached with a
/// layer, can be retrieved using [Layer.find] or [Layer.findAll] with a
/// position. The search process is done recursively, controlled by a concept
/// of being opaque to a type of annotation, explained in the document of
/// [Layer.findAnnotations].
/// layer, can be retrieved using [Layer.find] or [Layer.findAllAnnotations]
/// with a position. The search process is done recursively, controlled by a
/// concept of being opaque to a type of annotation, explained in the document
/// of [Layer.findAnnotations].
///
/// When an annotation search arrives, this layer defers the same search to each
/// of this layer's children, respecting their opacity. Then it adds this
Expand Down
8 changes: 4 additions & 4 deletions packages/flutter/lib/src/rendering/view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,13 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
///
/// See also:
///
/// * [Layer.findAll], which is used by this method to find all
/// * [Layer.findAllAnnotations], which is used by this method to find all
/// [AnnotatedRegionLayer]s annotated for mouse tracking.
Iterable<MouseTrackerAnnotation> hitTestMouseTrackers(Offset position) {
// Layer hit testing is done using device pixels, so we have to convert
// the logical coordinates of the event location back to device pixels
// here.
return layer.findAll<MouseTrackerAnnotation>(
return layer.findAllAnnotations<MouseTrackerAnnotation>(
position * configuration.devicePixelRatio
).annotations;
}
Expand Down Expand Up @@ -243,12 +243,12 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
final Rect bounds = paintBounds;
final Offset top = Offset(bounds.center.dx, _window.padding.top / _window.devicePixelRatio);
final Offset bottom = Offset(bounds.center.dx, bounds.center.dy - _window.padding.bottom / _window.devicePixelRatio);
final SystemUiOverlayStyle upperOverlayStyle = layer.find<SystemUiOverlayStyle>(top)?.annotation;
final SystemUiOverlayStyle upperOverlayStyle = layer.find<SystemUiOverlayStyle>(top);
// Only android has a customizable system navigation bar.
SystemUiOverlayStyle lowerOverlayStyle;
switch (defaultTargetPlatform) {
case TargetPlatform.android:
lowerOverlayStyle = layer.find<SystemUiOverlayStyle>(bottom)?.annotation;
lowerOverlayStyle = layer.find<SystemUiOverlayStyle>(bottom);
break;
case TargetPlatform.iOS:
case TargetPlatform.fuchsia:
Expand Down
Loading

0 comments on commit 1c535de

Please sign in to comment.