diff --git a/packages/flutter/lib/src/material/debug.dart b/packages/flutter/lib/src/material/debug.dart index 086a566ff6..12c4b1ae99 100644 --- a/packages/flutter/lib/src/material/debug.dart +++ b/packages/flutter/lib/src/material/debug.dart @@ -8,7 +8,7 @@ import 'material.dart'; bool debugCheckHasMaterial(BuildContext context) { assert(() { - if (context.widget is Material || context.ancestorWidgetOfType(Material) != null) + if (context.widget is Material || context.ancestorWidgetOfExactType(Material) != null) return true; Element element = context; debugPrint('${context.widget} needs to be placed inside a Material widget. Ownership chain:\n${element.debugGetOwnershipChain(10)}'); diff --git a/packages/flutter/lib/src/material/icon_theme.dart b/packages/flutter/lib/src/material/icon_theme.dart index d761fd4f37..e14c2e8a8f 100644 --- a/packages/flutter/lib/src/material/icon_theme.dart +++ b/packages/flutter/lib/src/material/icon_theme.dart @@ -20,7 +20,7 @@ class IconTheme extends InheritedWidget { /// The data from the closest instance of this class that encloses the given context. static IconThemeData of(BuildContext context) { - IconTheme result = context.inheritFromWidgetOfType(IconTheme); + IconTheme result = context.inheritFromWidgetOfExactType(IconTheme); return result?.data; } diff --git a/packages/flutter/lib/src/material/material.dart b/packages/flutter/lib/src/material/material.dart index 922d75ffdf..3dc1183bdf 100644 --- a/packages/flutter/lib/src/material/material.dart +++ b/packages/flutter/lib/src/material/material.dart @@ -95,7 +95,7 @@ class Material extends StatefulComponent { /// The ink controller from the closest instance of this class that encloses the given context. static MaterialInkController of(BuildContext context) { - final RenderInkFeatures result = context.ancestorRenderObjectOfType(RenderInkFeatures); + final RenderInkFeatures result = context.ancestorRenderObjectOfType(const TypeMatcher()); return result; } diff --git a/packages/flutter/lib/src/material/material_button.dart b/packages/flutter/lib/src/material/material_button.dart index 3052b45c5e..9ae0c19e62 100644 --- a/packages/flutter/lib/src/material/material_button.dart +++ b/packages/flutter/lib/src/material/material_button.dart @@ -27,7 +27,7 @@ class ButtonTheme extends InheritedWidget { /// /// Defaults to [ButtonColor.normal] if none exists. static ButtonColor of(BuildContext context) { - ButtonTheme result = context.inheritFromWidgetOfType(ButtonTheme); + ButtonTheme result = context.inheritFromWidgetOfExactType(ButtonTheme); return result?.color ?? ButtonColor.normal; } diff --git a/packages/flutter/lib/src/material/scaffold.dart b/packages/flutter/lib/src/material/scaffold.dart index 99696230c2..5a354076a7 100644 --- a/packages/flutter/lib/src/material/scaffold.dart +++ b/packages/flutter/lib/src/material/scaffold.dart @@ -110,7 +110,7 @@ class Scaffold extends StatefulComponent { final Widget drawer; /// The state from the closest instance of this class that encloses the given context. - static ScaffoldState of(BuildContext context) => context.ancestorStateOfType(ScaffoldState); + static ScaffoldState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher()); ScaffoldState createState() => new ScaffoldState(); } diff --git a/packages/flutter/lib/src/material/theme.dart b/packages/flutter/lib/src/material/theme.dart index be4f7a85de..ef0ff42047 100644 --- a/packages/flutter/lib/src/material/theme.dart +++ b/packages/flutter/lib/src/material/theme.dart @@ -26,7 +26,7 @@ class Theme extends InheritedWidget { /// /// Defaults to the fallback theme data if none exists. static ThemeData of(BuildContext context) { - Theme theme = context.inheritFromWidgetOfType(Theme); + Theme theme = context.inheritFromWidgetOfExactType(Theme); return theme?.data ?? _kFallbackTheme; } diff --git a/packages/flutter/lib/src/widgets/basic.dart b/packages/flutter/lib/src/widgets/basic.dart index 906bde34ca..ac828134b8 100644 --- a/packages/flutter/lib/src/widgets/basic.dart +++ b/packages/flutter/lib/src/widgets/basic.dart @@ -1411,7 +1411,7 @@ class DefaultTextStyle extends InheritedWidget { /// The style from the closest instance of this class that encloses the given context. static TextStyle of(BuildContext context) { - DefaultTextStyle result = context.inheritFromWidgetOfType(DefaultTextStyle); + DefaultTextStyle result = context.inheritFromWidgetOfExactType(DefaultTextStyle); return result?.style; } @@ -1737,7 +1737,7 @@ class DefaultAssetBundle extends InheritedWidget { /// The bundle from the closest instance of this class that encloses the given context. static AssetBundle of(BuildContext context) { - DefaultAssetBundle result = context.inheritFromWidgetOfType(DefaultAssetBundle); + DefaultAssetBundle result = context.inheritFromWidgetOfExactType(DefaultAssetBundle); return result?.bundle; } diff --git a/packages/flutter/lib/src/widgets/focus.dart b/packages/flutter/lib/src/widgets/focus.dart index cb65fc9a84..34cfde83f2 100644 --- a/packages/flutter/lib/src/widgets/focus.dart +++ b/packages/flutter/lib/src/widgets/focus.dart @@ -89,7 +89,7 @@ class Focus extends StatefulComponent { assert(context.widget != null); assert(context.widget.key != null); assert(context.widget.key is GlobalKey); - _FocusScope focusScope = context.inheritFromWidgetOfType(_FocusScope); + _FocusScope focusScope = context.inheritFromWidgetOfExactType(_FocusScope); if (focusScope != null) { if (autofocus) focusScope._setFocusedWidgetIfUnset(context.widget.key); @@ -113,7 +113,7 @@ class Focus extends StatefulComponent { assert(context != null); assert(context.widget != null); assert(context.widget is Focus); - _FocusScope focusScope = context.inheritFromWidgetOfType(_FocusScope); + _FocusScope focusScope = context.inheritFromWidgetOfExactType(_FocusScope); if (focusScope != null) { assert(context.widget.key != null); if (autofocus) @@ -131,7 +131,7 @@ class Focus extends StatefulComponent { /// called from event listeners, e.g. in response to a finger tap or tab key. static void moveTo(GlobalKey key) { assert(key.currentContext != null); - _FocusScope focusScope = key.currentContext.ancestorWidgetOfType(_FocusScope); + _FocusScope focusScope = key.currentContext.ancestorWidgetOfExactType(_FocusScope); if (focusScope != null) focusScope.focusState._setFocusedWidget(key); } @@ -144,7 +144,7 @@ class Focus extends StatefulComponent { static void moveScopeTo(GlobalKey key) { assert(key.currentWidget is Focus); assert(key.currentContext != null); - _FocusScope focusScope = key.currentContext.ancestorWidgetOfType(_FocusScope); + _FocusScope focusScope = key.currentContext.ancestorWidgetOfExactType(_FocusScope); if (focusScope != null) focusScope.focusState._setFocusedScope(key); } diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index 41fe02b2a8..66ebd1a6ef 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -198,6 +198,11 @@ class GlobalObjectKey extends GlobalKey { String toString() => '[$runtimeType ${value.runtimeType}(${value.hashCode})]'; } +/// This class is a work-around for the "is" operator not accepting a variable value as its right operand +class TypeMatcher { + const TypeMatcher(); + bool check(dynamic object) => object is T; +} // WIDGETS @@ -585,10 +590,10 @@ typedef void ElementVisitor(Element element); abstract class BuildContext { Widget get widget; RenderObject findRenderObject(); - InheritedWidget inheritFromWidgetOfType(Type targetType); - Widget ancestorWidgetOfType(Type targetType); - State ancestorStateOfType(Type targetType); - RenderObject ancestorRenderObjectOfType(Type targetType); + InheritedWidget inheritFromWidgetOfExactType(Type targetType); + Widget ancestorWidgetOfExactType(Type targetType); + State ancestorStateOfType(TypeMatcher matcher); + RenderObject ancestorRenderObjectOfType(TypeMatcher matcher); void visitAncestorElements(bool visitor(Element element)); void visitChildElements(void visitor(Element element)); } @@ -876,24 +881,24 @@ abstract class Element implements BuildContext { RenderObject findRenderObject() => renderObject; Set _dependencies; - InheritedWidget inheritFromWidgetOfType(Type targetType) { + InheritedWidget inheritFromWidgetOfExactType(Type targetType) { if (_dependencies == null) _dependencies = new Set(); _dependencies.add(targetType); - return ancestorWidgetOfType(targetType); + return ancestorWidgetOfExactType(targetType); } - Widget ancestorWidgetOfType(Type targetType) { + Widget ancestorWidgetOfExactType(Type targetType) { Element ancestor = _parent; while (ancestor != null && ancestor.widget.runtimeType != targetType) ancestor = ancestor._parent; return ancestor?.widget; } - State ancestorStateOfType(Type targetType) { + State ancestorStateOfType(TypeMatcher matcher) { Element ancestor = _parent; while (ancestor != null) { - if (ancestor is StatefulComponentElement && ancestor.state.runtimeType == targetType) + if (ancestor is StatefulComponentElement && matcher.check(ancestor.state)) break; ancestor = ancestor._parent; } @@ -901,10 +906,10 @@ abstract class Element implements BuildContext { return statefulAncestor?.state; } - RenderObject ancestorRenderObjectOfType(Type targetType) { + RenderObject ancestorRenderObjectOfType(TypeMatcher matcher) { Element ancestor = _parent; while (ancestor != null) { - if (ancestor is RenderObjectElement && ancestor.renderObject.runtimeType == targetType) + if (ancestor is RenderObjectElement && matcher.check(ancestor.renderObject)) break; ancestor = ancestor._parent; } diff --git a/packages/flutter/lib/src/widgets/locale_query.dart b/packages/flutter/lib/src/widgets/locale_query.dart index e944e65cac..bba7021207 100644 --- a/packages/flutter/lib/src/widgets/locale_query.dart +++ b/packages/flutter/lib/src/widgets/locale_query.dart @@ -20,7 +20,7 @@ class LocaleQuery extends InheritedWidget { /// The data from the closest instance of this class that encloses the given context. static LocaleQueryData of(BuildContext context) { - LocaleQuery query = context.inheritFromWidgetOfType(LocaleQuery); + LocaleQuery query = context.inheritFromWidgetOfExactType(LocaleQuery); return query == null ? null : query.data; } diff --git a/packages/flutter/lib/src/widgets/media_query.dart b/packages/flutter/lib/src/widgets/media_query.dart index 1d74b3b626..a652b48a58 100644 --- a/packages/flutter/lib/src/widgets/media_query.dart +++ b/packages/flutter/lib/src/widgets/media_query.dart @@ -58,7 +58,7 @@ class MediaQuery extends InheritedWidget { /// When that information changes, your widget will be scheduled to be rebuilt, /// keeping your widget up-to-date. static MediaQueryData of(BuildContext context) { - MediaQuery query = context.inheritFromWidgetOfType(MediaQuery); + MediaQuery query = context.inheritFromWidgetOfExactType(MediaQuery); return query == null ? null : query.data; } diff --git a/packages/flutter/lib/src/widgets/mimic.dart b/packages/flutter/lib/src/widgets/mimic.dart index 03c5c296df..09b4bc7f5b 100644 --- a/packages/flutter/lib/src/widgets/mimic.dart +++ b/packages/flutter/lib/src/widgets/mimic.dart @@ -111,7 +111,7 @@ class MimicOverlayEntry { } } - RenderBox stack = context.ancestorRenderObjectOfType(RenderStack); + RenderBox stack = context.ancestorRenderObjectOfType(const TypeMatcher()); // TODO(abarth): Handle the case where the transform here isn't just a translation. Point localPosition = stack == null ? globalPosition: stack.globalToLocal(globalPosition); return new Positioned( diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index b963ada452..210f5fe1f2 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -144,7 +144,7 @@ class Navigator extends StatefulComponent { } static bool canPop(BuildContext context) { - NavigatorState navigator = context.ancestorStateOfType(NavigatorState); + NavigatorState navigator = context.ancestorStateOfType(const TypeMatcher()); return navigator != null && navigator.canPop(); } @@ -156,7 +156,7 @@ class Navigator extends StatefulComponent { } static void openTransaction(BuildContext context, NavigatorTransactionCallback callback) { - NavigatorState navigator = context.ancestorStateOfType(NavigatorState); + NavigatorState navigator = context.ancestorStateOfType(const TypeMatcher()); navigator.openTransaction(callback); } diff --git a/packages/flutter/lib/src/widgets/overlay.dart b/packages/flutter/lib/src/widgets/overlay.dart index 07f5580b95..910dc40d8b 100644 --- a/packages/flutter/lib/src/widgets/overlay.dart +++ b/packages/flutter/lib/src/widgets/overlay.dart @@ -69,7 +69,7 @@ class Overlay extends StatefulComponent { final List initialEntries; /// The state from the closest instance of this class that encloses the given context. - static OverlayState of(BuildContext context) => context.ancestorStateOfType(OverlayState); + static OverlayState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher()); OverlayState createState() => new OverlayState(); } diff --git a/packages/flutter/lib/src/widgets/page_storage.dart b/packages/flutter/lib/src/widgets/page_storage.dart index 6213814451..585519e738 100644 --- a/packages/flutter/lib/src/widgets/page_storage.dart +++ b/packages/flutter/lib/src/widgets/page_storage.dart @@ -79,7 +79,7 @@ class PageStorage extends StatelessComponent { /// /// Returns null if none exists. static PageStorageBucket of(BuildContext context) { - PageStorage widget = context.ancestorWidgetOfType(PageStorage); + PageStorage widget = context.ancestorWidgetOfExactType(PageStorage); return widget?.bucket; } diff --git a/packages/flutter/lib/src/widgets/routes.dart b/packages/flutter/lib/src/widgets/routes.dart index f11388fb03..396e433d43 100644 --- a/packages/flutter/lib/src/widgets/routes.dart +++ b/packages/flutter/lib/src/widgets/routes.dart @@ -388,7 +388,7 @@ abstract class ModalRoute extends TransitionRoute with LocalHistoryRoute()); } /// Scrolls the closest enclosing scrollable to make the given context visible. diff --git a/packages/flutter/test/widget/page_forward_transitions_test.dart b/packages/flutter/test/widget/page_forward_transitions_test.dart index b92be39c2f..e7a3629dd0 100644 --- a/packages/flutter/test/widget/page_forward_transitions_test.dart +++ b/packages/flutter/test/widget/page_forward_transitions_test.dart @@ -5,7 +5,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/animation.dart'; import 'package:flutter/material.dart'; -import 'package:test/test.dart'; +import 'package:test/test.dart' hide TypeMatcher; class TestTransition extends TransitionComponent { TestTransition({ @@ -99,7 +99,7 @@ void main() { ) ); - NavigatorState navigator = insideKey.currentContext.ancestorStateOfType(NavigatorState); + NavigatorState navigator = insideKey.currentContext.ancestorStateOfType(const TypeMatcher()); expect(state(), equals('BC')); // transition ->1 is at 1.0