Port stocks to fn3 and introduce an App component.
diff --git a/examples/stocks/lib/main.dart b/examples/stocks/lib/main.dart index a70739b..aaacab0 100644 --- a/examples/stocks/lib/main.dart +++ b/examples/stocks/lib/main.dart
@@ -10,7 +10,8 @@ import 'package:sky/animation.dart'; import 'package:sky/material.dart'; -import 'package:sky/widgets.dart'; +import 'package:sky/painting.dart'; +import 'package:sky/src/fn3.dart'; import 'stock_data.dart'; @@ -22,53 +23,16 @@ part 'stock_settings.dart'; part 'stock_types.dart'; -class StocksApp extends App { +class StocksApp extends StatefulComponent { + StocksAppState createState() => new StocksAppState(); +} - NavigationState _navigationState; - - void initState() { - _navigationState = new NavigationState([ - new Route( - name: '/', - builder: (navigator, route) => new StockHome(navigator, _stocks, optimismSetting, modeUpdater) - ), - new Route( - name: '/settings', - builder: (navigator, route) => new StockSettings(navigator, optimismSetting, backupSetting, settingsUpdater) - ), - ]); - super.initState(); - } - - void onBack() { - if (_navigationState.hasPrevious()) { - setState(() { - _navigationState.pop(); - }); - } else { - super.onBack(); - } - } - - StockMode optimismSetting = StockMode.optimistic; - BackupMode backupSetting = BackupMode.disabled; - void modeUpdater(StockMode optimism) { - setState(() { - optimismSetting = optimism; - }); - } - void settingsUpdater({ StockMode optimism, BackupMode backup }) { - setState(() { - if (optimism != null) - optimismSetting = optimism; - if (backup != null) - backupSetting = backup; - }); - } +class StocksAppState extends State<StocksApp> { final List<Stock> _stocks = []; - void didMount() { - super.didMount(); + + void initState(BuildContext context) { + super.initState(context); new StockDataFetcher((StockData data) { setState(() { data.appendTo(_stocks); @@ -76,32 +40,47 @@ }); } - Widget build() { + StockMode _optimismSetting = StockMode.optimistic; + BackupMode _backupSetting = BackupMode.disabled; + void modeUpdater(StockMode optimism) { + setState(() { + _optimismSetting = optimism; + }); + } + void settingsUpdater({ StockMode optimism, BackupMode backup }) { + setState(() { + if (optimism != null) + _optimismSetting = optimism; + if (backup != null) + _backupSetting = backup; + }); + } - ThemeData theme; - if (optimismSetting == StockMode.optimistic) { - theme = new ThemeData( - brightness: ThemeBrightness.light, - primarySwatch: Colors.purple - ); - } else { - theme = new ThemeData( - brightness: ThemeBrightness.dark, - accentColor: Colors.redAccent[200] - ); + ThemeData get theme { + switch (_optimismSetting) { + case StockMode.optimistic: + return new ThemeData( + brightness: ThemeBrightness.light, + primarySwatch: Colors.purple + ); + case StockMode.pessimistic: + return new ThemeData( + brightness: ThemeBrightness.dark, + accentColor: Colors.redAccent[200] + ); } + } - return new Theme( - data: theme, - child: new DefaultTextStyle( - style: Typography.error, // if you see this, you've forgotten to correctly configure the text style! - child: new Title( - title: 'Stocks', - child: new Navigator(_navigationState) - ) - ) - ); - } + Widget build(BuildContext context) { + return new App( + title: 'Stocks', + theme: theme, + routes: <String, RouteBuilder>{ + '/': (navigator, route) => new StockHome(navigator, _stocks, _optimismSetting, modeUpdater), + '/settings': (navigator, route) => new StockSettings(navigator, _optimismSetting, _backupSetting, settingsUpdater) + } + ); + } } void main() {
diff --git a/examples/stocks/lib/stock_arrow.dart b/examples/stocks/lib/stock_arrow.dart index 394eda3..a1f56b5 100644 --- a/examples/stocks/lib/stock_arrow.dart +++ b/examples/stocks/lib/stock_arrow.dart
@@ -4,8 +4,7 @@ part of stocks; -class StockArrow extends Component { - +class StockArrow extends StatelessComponent { StockArrow({ Key key, this.percentChange }) : super(key: key); final double percentChange; @@ -22,7 +21,7 @@ return Colors.red[_colorIndexForPercentChange(percentChange)]; } - Widget build() { + Widget build(BuildContext context) { // TODO(jackson): This should change colors with the theme Color color = _colorForPercentChange(percentChange); const double kSize = 40.0; @@ -65,5 +64,4 @@ margin: const EdgeDims.symmetric(horizontal: 5.0) ); } - }
diff --git a/examples/stocks/lib/stock_home.dart b/examples/stocks/lib/stock_home.dart index c85dd54..ee47f6e 100644 --- a/examples/stocks/lib/stock_home.dart +++ b/examples/stocks/lib/stock_home.dart
@@ -9,20 +9,17 @@ const Duration _kSnackbarSlideDuration = const Duration(milliseconds: 200); class StockHome extends StatefulComponent { - StockHome(this.navigator, this.stocks, this.stockMode, this.modeUpdater); - Navigator navigator; - List<Stock> stocks; - StockMode stockMode; - ModeUpdater modeUpdater; + final NavigatorState navigator; + final List<Stock> stocks; + final StockMode stockMode; + final ModeUpdater modeUpdater; - void syncConstructorArguments(StockHome source) { - navigator = source.navigator; - stocks = source.stocks; - stockMode = source.stockMode; - modeUpdater = source.modeUpdater; - } + StockHomeState createState() => new StockHomeState(); +} + +class StockHomeState extends State<StockHome> { bool _isSearching = false; String _searchQuery; @@ -31,7 +28,7 @@ bool _isSnackBarShowing = false; void _handleSearchBegin() { - navigator.pushState(this, (_) { + config.navigator.pushState(this, (_) { setState(() { _isSearching = false; _searchQuery = null; @@ -43,9 +40,9 @@ } void _handleSearchEnd() { - assert(navigator.currentRoute is RouteState); - assert((navigator.currentRoute as RouteState).owner == this); // TODO(ianh): remove cast once analyzer is cleverer - navigator.pop(); + assert(config.navigator.currentRoute is RouteState); + assert((config.navigator.currentRoute as RouteState).owner == this); // TODO(ianh): remove cast once analyzer is cleverer + config.navigator.pop(); setState(() { _isSearching = false; _searchQuery = null; @@ -82,15 +79,12 @@ } void _handleStockModeChange(StockMode value) { - setState(() { - stockMode = value; - }); - if (modeUpdater != null) - modeUpdater(value); + if (config.modeUpdater != null) + config.modeUpdater(value); } void _handleMenuShow() { - showStockMenu(navigator, + showStockMenu(config.navigator, autorefresh: _autorefresh, onAutorefreshChanged: _handleAutorefreshChanged ); @@ -104,7 +98,7 @@ level: 3, showing: _drawerShowing, onDismissed: _handleDrawerDismissed, - navigator: navigator, + navigator: config.navigator, children: [ new DrawerHeader(child: new Text('Stocks')), new DrawerItem( @@ -122,7 +116,7 @@ onPressed: () => _handleStockModeChange(StockMode.optimistic), child: new Row([ new Flexible(child: new Text('Optimistic')), - new Radio(value: StockMode.optimistic, groupValue: stockMode, onChanged: _handleStockModeChange) + new Radio(value: StockMode.optimistic, groupValue: config.stockMode, onChanged: _handleStockModeChange) ]) ), new DrawerItem( @@ -130,7 +124,7 @@ onPressed: () => _handleStockModeChange(StockMode.pessimistic), child: new Row([ new Flexible(child: new Text('Pessimistic')), - new Radio(value: StockMode.pessimistic, groupValue: stockMode, onChanged: _handleStockModeChange) + new Radio(value: StockMode.pessimistic, groupValue: config.stockMode, onChanged: _handleStockModeChange) ]) ), new DrawerDivider(), @@ -146,23 +140,26 @@ } void _handleShowSettings() { - navigator.pop(); - navigator.pushNamed('/settings'); + config.navigator.pop(); + config.navigator.pushNamed('/settings'); } Widget buildToolBar() { return new ToolBar( left: new IconButton( icon: "navigation/menu", - onPressed: _handleOpenDrawer), + onPressed: _handleOpenDrawer + ), center: new Text('Stocks'), right: [ new IconButton( icon: "action/search", - onPressed: _handleSearchBegin), + onPressed: _handleSearchBegin + ), new IconButton( icon: "navigation/more_vert", - onPressed: _handleMenuShow) + onPressed: _handleMenuShow + ) ] ); } @@ -181,12 +178,12 @@ return stocks.where((stock) => stock.symbol.contains(regexp)); } - Widget buildMarketStockList() { - return new Stocklist(stocks: _filterBySearchQuery(stocks).toList()); + Widget buildMarketStockList(BuildContext context) { + return new Stocklist(stocks: _filterBySearchQuery(config.stocks).toList()); } - Widget buildPortfolioStocklist() { - return new Stocklist(stocks: _filterBySearchQuery(_filterByPortfolio(stocks)).toList()); + Widget buildPortfolioStocklist(BuildContext context) { + return new Stocklist(stocks: _filterBySearchQuery(_filterByPortfolio(config.stocks)).toList()); } Widget buildTabNavigator() { @@ -216,7 +213,7 @@ return new ToolBar( left: new IconButton( icon: "navigation/arrow_back", - color: Theme.of(this).accentColor, + color: Theme.of(context).accentColor, onPressed: _handleSearchEnd ), center: new Input( @@ -224,7 +221,7 @@ placeholder: 'Search stocks', onChanged: _handleSearchQueryChanged ), - backgroundColor: Theme.of(this).canvasColor + backgroundColor: Theme.of(context).canvasColor ); } @@ -255,17 +252,14 @@ } Widget buildFloatingActionButton() { - return new TransitionProxy( - transitionKey: snackBarKey, - child: new FloatingActionButton( - child: new Icon(type: 'content/add', size: 24), - backgroundColor: Colors.redAccent[200], - onPressed: _handleStockPurchased - ) + return new FloatingActionButton( + child: new Icon(type: 'content/add', size: 24), + backgroundColor: Colors.redAccent[200], + onPressed: _handleStockPurchased ); } - Widget build() { + Widget build(BuildContext context) { return new Scaffold( toolbar: _isSearching ? buildSearchBar() : buildToolBar(), body: buildTabNavigator(),
diff --git a/examples/stocks/lib/stock_list.dart b/examples/stocks/lib/stock_list.dart index 42ea384..a65d735 100644 --- a/examples/stocks/lib/stock_list.dart +++ b/examples/stocks/lib/stock_list.dart
@@ -4,18 +4,18 @@ part of stocks; -class Stocklist extends Component { +class Stocklist extends StatelessComponent { Stocklist({ Key key, this.stocks }) : super(key: key); final List<Stock> stocks; - Widget build() { + Widget build(BuildContext context) { return new Material( type: MaterialType.canvas, child: new ScrollableList<Stock>( items: stocks, itemExtent: StockRow.kHeight, - itemBuilder: (Stock stock) => new StockRow(stock: stock) + itemBuilder: (BuildContext context, Stock stock) => new StockRow(stock: stock) ) ); }
diff --git a/examples/stocks/lib/stock_menu.dart b/examples/stocks/lib/stock_menu.dart index a61073a..f9c3278 100644 --- a/examples/stocks/lib/stock_menu.dart +++ b/examples/stocks/lib/stock_menu.dart
@@ -4,19 +4,27 @@ part of stocks; -Future showStockMenu(Navigator navigator, { bool autorefresh, ValueChanged onAutorefreshChanged }) { - return showMenu( +enum _MenuItems { add, remove, autorefresh } + +Future showStockMenu(NavigatorState navigator, { bool autorefresh, ValueChanged onAutorefreshChanged }) async { + switch (await showMenu( navigator: navigator, position: new MenuPosition( right: sky.view.paddingRight, top: sky.view.paddingTop ), - builder: (Navigator navigator) { + builder: (NavigatorState navigator) { return <PopupMenuItem>[ - new PopupMenuItem(child: new Text('Add stock')), - new PopupMenuItem(child: new Text('Remove stock')), new PopupMenuItem( - onPressed: () => onAutorefreshChanged(!autorefresh), + value: _MenuItems.add, + child: new Text('Add stock') + ), + new PopupMenuItem( + value: _MenuItems.remove, + child: new Text('Remove stock') + ), + new PopupMenuItem( + value: _MenuItems.autorefresh, child: new Row([ new Flexible(child: new Text('Autorefresh')), new Checkbox( @@ -28,5 +36,28 @@ ), ]; } - ); + )) { + case _MenuItems.autorefresh: + onAutorefreshChanged(!autorefresh); + break; + case _MenuItems.add: + case _MenuItems.remove: + await showDialog(navigator, (NavigatorState navigator) { + return new Dialog( + title: new Text('Not Implemented'), + content: new Text('This feature has not yet been implemented.'), + actions: [ + new FlatButton( + child: new Text('OH WELL'), + onPressed: () { + navigator.pop(false); + } + ), + ] + ); + }); + break; + default: + // menu was canceled. + } } \ No newline at end of file
diff --git a/examples/stocks/lib/stock_row.dart b/examples/stocks/lib/stock_row.dart index f2f4e68..4ebe859 100644 --- a/examples/stocks/lib/stock_row.dart +++ b/examples/stocks/lib/stock_row.dart
@@ -4,15 +4,14 @@ part of stocks; -class StockRow extends Component { - +class StockRow extends StatelessComponent { StockRow({ Stock stock }) : this.stock = stock, super(key: new Key(stock.symbol)); final Stock stock; static const double kHeight = 79.0; - Widget build() { + Widget build(BuildContext context) { String lastSale = "\$${stock.lastSale.toStringAsFixed(2)}"; String changeInPrice = "${stock.percentChange.toStringAsFixed(2)}%"; @@ -32,7 +31,7 @@ new Flexible( child: new Text( changeInPrice, - style: Theme.of(this).text.caption.copyWith(textAlign: TextAlign.right) + style: Theme.of(context).text.caption.copyWith(textAlign: TextAlign.right) ) ) ]; @@ -43,7 +42,7 @@ height: kHeight, decoration: new BoxDecoration( border: new Border( - bottom: new BorderSide(color: Theme.of(this).dividerColor) + bottom: new BorderSide(color: Theme.of(context).dividerColor) ) ), child: new Row([ @@ -55,7 +54,7 @@ child: new Row( children, alignItems: FlexAlignItems.baseline, - textBaseline: DefaultTextStyle.of(this).textBaseline + textBaseline: DefaultTextStyle.of(context).textBaseline ) ) ])
diff --git a/examples/stocks/lib/stock_settings.dart b/examples/stocks/lib/stock_settings.dart index 19f3125..269afe1 100644 --- a/examples/stocks/lib/stock_settings.dart +++ b/examples/stocks/lib/stock_settings.dart
@@ -10,42 +10,32 @@ }); class StockSettings extends StatefulComponent { + const StockSettings(this.navigator, this.optimism, this.backup, this.updater); - StockSettings(this.navigator, this.optimism, this.backup, this.updater); + final NavigatorState navigator; + final StockMode optimism; + final BackupMode backup; + final SettingsUpdater updater; - Navigator navigator; - StockMode optimism; - BackupMode backup; - SettingsUpdater updater; + StockSettingsState createState() => new StockSettingsState(); +} - void syncConstructorArguments(StockSettings source) { - navigator = source.navigator; - optimism = source.optimism; - backup = source.backup; - updater = source.updater; - } - +class StockSettingsState extends State<StockSettings> { void _handleOptimismChanged(bool value) { - setState(() { - optimism = value ? StockMode.optimistic : StockMode.pessimistic; - }); - sendUpdates(); + sendUpdates(value ? StockMode.optimistic : StockMode.pessimistic, config.backup); } void _handleBackupChanged(bool value) { - setState(() { - backup = value ? BackupMode.enabled : BackupMode.disabled; - }); - sendUpdates(); + sendUpdates(config.optimism, value ? BackupMode.enabled : BackupMode.disabled); } void _confirmOptimismChange() { - switch (optimism) { + switch (config.optimism) { case StockMode.optimistic: _handleOptimismChanged(false); break; case StockMode.pessimistic: - showDialog(navigator, (navigator) { + showDialog(config.navigator, (NavigatorState navigator) { return new Dialog( title: new Text("Change mode?"), content: new Text("Optimistic mode means everything is awesome. Are you sure you can handle that?"), @@ -72,24 +62,25 @@ } } - void sendUpdates() { - if (updater != null) - updater( + void sendUpdates(StockMode optimism, BackupMode backup) { + if (config.updater != null) + config.updater( optimism: optimism, backup: backup ); } - Widget buildToolBar() { + Widget buildToolBar(BuildContext context) { return new ToolBar( left: new IconButton( icon: 'navigation/arrow_back', - onPressed: navigator.pop), + onPressed: config.navigator.pop + ), center: new Text('Settings') ); } - Widget buildSettingsPane() { + Widget buildSettingsPane(BuildContext context) { // TODO(ianh): Once we have the gesture API hooked up, fix https://github.com/domokit/mojo/issues/281 // (whereby tapping the widgets below causes both the widget and the menu item to fire their callbacks) return new Material( @@ -103,15 +94,21 @@ onPressed: () => _confirmOptimismChange(), child: new Row([ new Flexible(child: new Text('Everything is awesome')), - new Checkbox(value: optimism == StockMode.optimistic, onChanged: (_) => _confirmOptimismChange()), + new Checkbox( + value: config.optimism == StockMode.optimistic, + onChanged: (_) => _confirmOptimismChange() + ), ]) ), new DrawerItem( icon: 'action/backup', - onPressed: () { _handleBackupChanged(!(backup == BackupMode.enabled)); }, + onPressed: () { _handleBackupChanged(!(config.backup == BackupMode.enabled)); }, child: new Row([ new Flexible(child: new Text('Back up stock list to the cloud')), - new Switch(value: backup == BackupMode.enabled, onChanged: _handleBackupChanged), + new Switch( + value: config.backup == BackupMode.enabled, + onChanged: _handleBackupChanged + ), ]) ), ]) @@ -120,10 +117,10 @@ ); } - Widget build() { + Widget build(BuildContext context) { return new Scaffold( - toolbar: buildToolBar(), - body: buildSettingsPane() + toolbar: buildToolBar(context), + body: buildSettingsPane(context) ); } }