diff --git a/examples/address_book/lib/main.dart b/examples/address_book/lib/main.dart index c12a7d2114b..2bca9be10fb 100644 --- a/examples/address_book/lib/main.dart +++ b/examples/address_book/lib/main.dart @@ -101,7 +101,7 @@ void main() { title: 'Address Book', theme: theme, routes: { - '/': (NavigatorState navigator, Route route) => new AddressBookHome(navigator: navigator) + '/': (RouteArguments args) => new AddressBookHome(navigator: args.navigator) } )); } diff --git a/examples/demo_launcher/lib/main.dart b/examples/demo_launcher/lib/main.dart index 4fc089c33d0..2bbef2362be 100644 --- a/examples/demo_launcher/lib/main.dart +++ b/examples/demo_launcher/lib/main.dart @@ -206,7 +206,7 @@ void main() { title: 'Flutter Demos', theme: _theme, routes: { - '/': (NavigatorState navigator, Route route) => new DemoHome() + '/': (RouteArguments args) => new DemoHome() } )); } diff --git a/examples/fitness/lib/main.dart b/examples/fitness/lib/main.dart index 1f12e111a50..98f87db579b 100644 --- a/examples/fitness/lib/main.dart +++ b/examples/fitness/lib/main.dart @@ -92,8 +92,6 @@ class FitnessApp extends StatefulComponent { class FitnessAppState extends State { UserDataImpl _userData; - Map _routes; - void initState() { super.initState(); loadFitnessData().then((UserData data) { @@ -102,36 +100,6 @@ class FitnessAppState extends State { print("Failed to load data: $e"); setState(() => _userData = new UserDataImpl()); }); - - _routes = { - '/': (NavigatorState navigator, Route route) { - return new FeedFragment( - navigator: navigator, - userData: _userData, - onItemCreated: _handleItemCreated, - onItemDeleted: _handleItemDeleted - ); - }, - '/meals/new': (navigator, route) { - return new MealFragment( - navigator: navigator, - onCreated: _handleItemCreated - ); - }, - '/measurements/new': (NavigatorState navigator, Route route) { - return new MeasurementFragment( - navigator: navigator, - onCreated: _handleItemCreated - ); - }, - '/settings': (navigator, route) { - return new SettingsFragment( - navigator: navigator, - userData: _userData, - updater: settingsUpdater - ); - } - }; } void _handleItemCreated(FitnessItem item) { @@ -158,17 +126,43 @@ class FitnessAppState extends State { }); } - final ThemeData _theme = new ThemeData( - brightness: ThemeBrightness.light, - primarySwatch: Colors.indigo, - accentColor: Colors.pinkAccent[200] - ); - Widget build(BuildContext) { return new App( - theme: _theme, + theme: new ThemeData( + brightness: ThemeBrightness.light, + primarySwatch: Colors.indigo, + accentColor: Colors.pinkAccent[200] + ), title: 'Fitness', - routes: _routes + routes: { + '/': (RouteArguments args) { + return new FeedFragment( + navigator: args.navigator, + userData: _userData, + onItemCreated: _handleItemCreated, + onItemDeleted: _handleItemDeleted + ); + }, + '/meals/new': (RouteArguments args) { + return new MealFragment( + navigator: args.navigator, + onCreated: _handleItemCreated + ); + }, + '/measurements/new': (RouteArguments args) { + return new MeasurementFragment( + navigator: args.navigator, + onCreated: _handleItemCreated + ); + }, + '/settings': (RouteArguments args) { + return new SettingsFragment( + navigator: args.navigator, + userData: _userData, + updater: settingsUpdater + ); + } + } ); } } diff --git a/examples/game/example_effect_line.dart b/examples/game/example_effect_line.dart index 4a6e7cc150d..05323d00d9d 100644 --- a/examples/game/example_effect_line.dart +++ b/examples/game/example_effect_line.dart @@ -62,7 +62,7 @@ class TestAppState extends State { ); } - Column _buildColumn(NavigatorState navigator, Route route) { + Column _buildColumn(RouteArguments args) { return new Column([ new Flexible(child: _buildSpriteWidget()), _buildTabBar() diff --git a/examples/game/lib/main.dart b/examples/game/lib/main.dart index a93038d44d4..2cb407aa393 100644 --- a/examples/game/lib/main.dart +++ b/examples/game/lib/main.dart @@ -92,11 +92,11 @@ class GameDemoState extends State { ); } - Widget _buildGameScene(NavigatorState navigator, Route route) { + Widget _buildGameScene(RouteArguments args) { return new SpriteWidget(_game, SpriteBoxTransformMode.fixedWidth); } - Widget _buildMainScene(navigator, route) { + Widget _buildMainScene(RouteArguments args) { return new Stack([ new SpriteWidget(new MainScreenBackground(), SpriteBoxTransformMode.fixedWidth), new Column([ @@ -109,10 +109,10 @@ class GameDemoState extends State { _sounds, (lastScore) { setState(() {_lastScore = lastScore;}); - navigator.pop(); + args.navigator.pop(); } ); - navigator.pushNamed('/game'); + args.navigator.pushNamed('/game'); }, texture: _spriteSheetUI['btn_play_up.png'], textureDown: _spriteSheetUI['btn_play_down.png'], diff --git a/examples/game/test_drawatlas.dart b/examples/game/test_drawatlas.dart index 135334eccc2..dba1748a259 100644 --- a/examples/game/test_drawatlas.dart +++ b/examples/game/test_drawatlas.dart @@ -36,7 +36,7 @@ main() async { title: 'Test drawAtlas', theme: _theme, routes: { - '/': (NavigatorState navigator, Route route) { + '/': (RouteArguments args) { return new SpriteWidget( new TestDrawAtlas(), SpriteBoxTransformMode.fixedWidth diff --git a/examples/game/test_physics.dart b/examples/game/test_physics.dart index 2a9ad884ac0..aabb773bd2a 100644 --- a/examples/game/test_physics.dart +++ b/examples/game/test_physics.dart @@ -34,7 +34,7 @@ main() async { primarySwatch: Colors.purple ), routes: { - '/': (navigator, route) { + '/': (RouteArguments args) { return new SpriteWidget( new TestBed(), SpriteBoxTransformMode.letterbox diff --git a/examples/stocks/lib/main.dart b/examples/stocks/lib/main.dart index 4b2c1e89c39..a931d547eaa 100644 --- a/examples/stocks/lib/main.dart +++ b/examples/stocks/lib/main.dart @@ -82,7 +82,7 @@ class StocksAppState extends State { if (path.length != 3) return null; if (_stocks.containsKey(path[2])) - return (navigator, route) => new StockSymbolViewer(navigator, _stocks[path[2]]); + return (RouteArguments args) => new StockSymbolViewer(args.navigator, _stocks[path[2]]); return null; } return null; @@ -93,8 +93,8 @@ class StocksAppState extends State { title: 'Stocks', theme: theme, routes: { - '/': (navigator, route) => new StockHome(navigator, _stocks, _symbols, _optimismSetting, modeUpdater), - '/settings': (navigator, route) => new StockSettings(navigator, _optimismSetting, _backupSetting, settingsUpdater) + '/': (RouteArguments args) => new StockHome(args.navigator, _stocks, _symbols, _optimismSetting, modeUpdater), + '/settings': (RouteArguments args) => new StockSettings(args.navigator, _optimismSetting, _backupSetting, settingsUpdater) }, onGenerateRoute: _getRoute ); diff --git a/examples/widgets/card_collection.dart b/examples/widgets/card_collection.dart index 0e7a06c4f52..fb0458b0ab7 100644 --- a/examples/widgets/card_collection.dart +++ b/examples/widgets/card_collection.dart @@ -357,7 +357,7 @@ void main() { accentColor: Colors.redAccent[200] ), routes: { - '/': (NavigatorState navigator, Route route) => new CardCollection(navigator: navigator), + '/': (RouteArguments args) => new CardCollection(navigator: args.navigator), } )); } diff --git a/examples/widgets/drag_and_drop.dart b/examples/widgets/drag_and_drop.dart index c7a618763dc..f35934c3af2 100644 --- a/examples/widgets/drag_and_drop.dart +++ b/examples/widgets/drag_and_drop.dart @@ -133,7 +133,7 @@ void main() { runApp(new App( title: 'Drag and Drop Flutter Demo', routes: { - '/': (NavigatorState navigator, Route route) => new DragAndDropApp(navigator: navigator) + '/': (RouteArguments args) => new DragAndDropApp(navigator: args.navigator) } )); } diff --git a/examples/widgets/navigation.dart b/examples/widgets/navigation.dart index c9dd69b1613..7ade991408a 100644 --- a/examples/widgets/navigation.dart +++ b/examples/widgets/navigation.dart @@ -6,46 +6,46 @@ import 'package:sky/material.dart'; import 'package:sky/widgets.dart'; final Map routes = { - '/': (NavigatorState navigator, Route route) => new Container( + '/': (RouteArguments args) => new Container( padding: const EdgeDims.all(30.0), decoration: new BoxDecoration(backgroundColor: const Color(0xFFCCCCCC)), child: new Column([ new Text("You are at home"), new RaisedButton( child: new Text('GO SHOPPING'), - onPressed: () => navigator.pushNamed('/shopping') + onPressed: () => args.navigator.pushNamed('/shopping') ), new RaisedButton( child: new Text('START ADVENTURE'), - onPressed: () => navigator.pushNamed('/adventure') + onPressed: () => args.navigator.pushNamed('/adventure') )], justifyContent: FlexJustifyContent.center ) ), - '/shopping': (NavigatorState navigator, Route route) => new Container( + '/shopping': (RouteArguments args) => new Container( padding: const EdgeDims.all(20.0), decoration: new BoxDecoration(backgroundColor: const Color(0xFFBF5FFF)), child: new Column([ new Text("Village Shop"), new RaisedButton( child: new Text('RETURN HOME'), - onPressed: () => navigator.pop() + onPressed: () => args.navigator.pop() ), new RaisedButton( child: new Text('GO TO DUNGEON'), - onPressed: () => navigator.pushNamed('/adventure') + onPressed: () => args.navigator.pushNamed('/adventure') )], justifyContent: FlexJustifyContent.center ) ), - '/adventure': (NavigatorState navigator, Route route) => new Container( + '/adventure': (RouteArguments args) => new Container( padding: const EdgeDims.all(20.0), decoration: new BoxDecoration(backgroundColor: const Color(0xFFDC143C)), child: new Column([ new Text("Monster's Lair"), new RaisedButton( child: new Text('RUN!!!'), - onPressed: () => navigator.pop() + onPressed: () => args.navigator.pop() )], justifyContent: FlexJustifyContent.center ) diff --git a/examples/widgets/overlay_geometry.dart b/examples/widgets/overlay_geometry.dart index 8a525204d48..6aa66e91ed3 100644 --- a/examples/widgets/overlay_geometry.dart +++ b/examples/widgets/overlay_geometry.dart @@ -165,7 +165,7 @@ void main() { ), title: 'Cards', routes: { - '/': (navigator, route) => new OverlayGeometryApp() + '/': (RouteArguments args) => new OverlayGeometryApp() } )); } diff --git a/examples/widgets/pageable_list.dart b/examples/widgets/pageable_list.dart index c00da4b488e..e68ebbc87ad 100644 --- a/examples/widgets/pageable_list.dart +++ b/examples/widgets/pageable_list.dart @@ -165,7 +165,7 @@ void main() { accentColor: Colors.redAccent[200] ), routes: { - '/': (NavigatorState navigator, Route route) => new PageableListApp(navigator: navigator), + '/': (RouteArguments args) => new PageableListApp(navigator: args.navigator), } )); } diff --git a/packages/flutter/lib/src/widgets/dialog.dart b/packages/flutter/lib/src/widgets/dialog.dart index 54c2a6f1747..4efe02b5a94 100644 --- a/packages/flutter/lib/src/widgets/dialog.dart +++ b/packages/flutter/lib/src/widgets/dialog.dart @@ -145,7 +145,7 @@ class DialogRoute extends Route { return new FadeTransition( performance: performance, opacity: new AnimatedValue(0.0, end: 1.0, curve: easeOut), - child: builder(navigator, this) + child: builder(new RouteArguments(navigator: navigator, previousPerformance: this.performance, nextPerformance: nextRoutePerformance)) ); } @@ -159,11 +159,11 @@ Future showDialog(NavigatorState navigator, DialogBuilder builder) { Completer completer = new Completer(); navigator.push(new DialogRoute( completer: completer, - builder: (navigator, route) { + builder: (RouteArguments args) { return new Focus( - key: new GlobalObjectKey(route), + key: new GlobalObjectKey(completer), autofocus: true, - child: builder(navigator) + child: builder(args.navigator) ); } )); diff --git a/packages/flutter/lib/src/widgets/drawer.dart b/packages/flutter/lib/src/widgets/drawer.dart index 945542c5dda..1d73b9fc84b 100644 --- a/packages/flutter/lib/src/widgets/drawer.dart +++ b/packages/flutter/lib/src/widgets/drawer.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:async'; - import 'package:sky/animation.dart'; import 'package:sky/material.dart'; import 'package:sky/src/widgets/animated_container.dart'; @@ -11,7 +9,6 @@ import 'package:sky/src/widgets/framework.dart'; import 'package:sky/src/widgets/basic.dart'; import 'package:sky/src/widgets/gesture_detector.dart'; import 'package:sky/src/widgets/navigator.dart'; -import 'package:sky/src/widgets/scrollable.dart'; import 'package:sky/src/widgets/theme.dart'; import 'package:sky/src/widgets/transitions.dart'; import 'package:sky/src/widgets/focus.dart'; diff --git a/packages/flutter/lib/src/widgets/framework.dart b/packages/flutter/lib/src/widgets/framework.dart index c0cce2b28fa..0d769af67c4 100644 --- a/packages/flutter/lib/src/widgets/framework.dart +++ b/packages/flutter/lib/src/widgets/framework.dart @@ -486,9 +486,11 @@ final _InactiveElements _inactiveElements = new _InactiveElements(); typedef void ElementVisitor(Element element); abstract class BuildContext { - InheritedWidget inheritedWidgetOfType(Type targetType); + Widget get widget; RenderObject findRenderObject(); + InheritedWidget inheritedWidgetOfType(Type targetType); void visitAncestorElements(bool visitor(Element element)); + void visitChildElements(void visitor(Element element)); } /// Elements are the instantiations of Widget configurations. @@ -540,6 +542,13 @@ abstract class Element implements BuildContext { /// Calls the argument for each child. Must be overridden by subclasses that support having children. void visitChildren(ElementVisitor visitor) { } + /// Wrapper around visitChildren for BuildContext. + void visitChildElements(void visitor(Element element)) { + // don't allow visitChildElements() during build, since children aren't necessarily built yet + assert(BuildableElement._debugStateLockLevel == 0); + visitChildren(visitor); + } + bool detachChild(Element child) => false; /// This method is the core of the system. @@ -952,11 +961,11 @@ abstract class BuildableElement extends Element { /// Instantiation of StatelessComponent widgets. class StatelessComponentElement extends BuildableElement { - StatelessComponentElement(StatelessComponent widget) : super(widget) { + StatelessComponentElement(T widget) : super(widget) { _builder = widget.build; } - void update(StatelessComponent newWidget) { + void update(T newWidget) { super.update(newWidget); assert(widget == newWidget); _builder = widget.build; @@ -966,10 +975,10 @@ class StatelessComponentElement extends BuildableE } /// Instantiation of StatefulComponent widgets. -class StatefulComponentElement extends BuildableElement { - StatefulComponentElement(StatefulComponent widget) +class StatefulComponentElement> extends BuildableElement { + StatefulComponentElement(T widget) : _state = widget.createState(), super(widget) { - assert(_state._debugTypesAreRight(widget)); + assert(_state._debugTypesAreRight(widget)); // can't use T and U, since normally we don't actually set those assert(_state._element == null); _state._element = this; assert(_builder == null); @@ -992,10 +1001,10 @@ class StatefulComponentElement extends BuildableElement { assert(() { _state._debugLifecycleState = _StateLifecycle.ready; return true; }); } - State get state => _state; - State _state; + U get state => _state; + U _state; - void update(StatefulComponent newWidget) { + void update(T newWidget) { super.update(newWidget); assert(widget == newWidget); StatefulComponent oldConfig = _state._config; diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index 7df0d8fe0a4..f47c70ad5b2 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -8,7 +8,14 @@ import 'package:sky/src/widgets/focus.dart'; import 'package:sky/src/widgets/framework.dart'; import 'package:sky/src/widgets/transitions.dart'; -typedef Widget RouteBuilder(NavigatorState navigator, Route route); +class RouteArguments { + const RouteArguments({ this.navigator, this.previousPerformance, this.nextPerformance }); + final NavigatorState navigator; + final PerformanceView previousPerformance; + final PerformanceView nextPerformance; +} + +typedef Widget RouteBuilder(RouteArguments args); typedef RouteBuilder RouteGenerator(String name); typedef void StateRouteCallback(StateRoute route); typedef void NotificationCallback(); @@ -154,6 +161,7 @@ class NavigatorState extends State { } return new Focus(child: new Stack(visibleRoutes.reversed.toList())); } + } @@ -272,7 +280,7 @@ class PageRoute extends Route { child: new FadeTransition( performance: performance, opacity: new AnimatedValue(0.0, end: 1.0, curve: easeOut), - child: builder(navigator, this) + child: builder(new RouteArguments(navigator: navigator, previousPerformance: this.performance, nextPerformance: nextRoutePerformance)) ) ); } diff --git a/packages/unit/test/widget/draggable_test.dart b/packages/unit/test/widget/draggable_test.dart index 31120bc3764..8e8b224d2aa 100644 --- a/packages/unit/test/widget/draggable_test.dart +++ b/packages/unit/test/widget/draggable_test.dart @@ -13,9 +13,9 @@ void main() { tester.pumpWidget(new Navigator( routes: { - '/': (NavigatorState navigator, Route route) { return new Column([ + '/': (RouteArguments args) { return new Column([ new Draggable( - navigator: navigator, + navigator: args.navigator, data: 1, child: new Text('Source'), feedback: new Text('Dragging') diff --git a/packages/unit/test/widget/navigator_test.dart b/packages/unit/test/widget/navigator_test.dart index 5da23d03ef7..a9bfcd5e630 100644 --- a/packages/unit/test/widget/navigator_test.dart +++ b/packages/unit/test/widget/navigator_test.dart @@ -49,8 +49,8 @@ void main() { test('Can navigator navigate to and from a stateful component', () { testWidgets((WidgetTester tester) { final Map routes = { - '/': (navigator, route) => new FirstComponent(navigator), - '/second': (navigator, route) => new SecondComponent(navigator), + '/': (RouteArguments args) => new FirstComponent(args.navigator), + '/second': (RouteArguments args) => new SecondComponent(args.navigator), }; tester.pumpWidget(new Navigator(routes: routes));