| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 import 'package:sky/framework/components/action_bar.dart'; | 5 import 'package:sky/framework/components/action_bar.dart'; |
| 6 import 'package:sky/framework/components/drawer.dart'; | 6 import 'package:sky/framework/components/drawer.dart'; |
| 7 import 'package:sky/framework/components/drawer_header.dart'; | 7 import 'package:sky/framework/components/drawer_header.dart'; |
| 8 import 'package:sky/framework/components/floating_action_button.dart'; | 8 import 'package:sky/framework/components/floating_action_button.dart'; |
| 9 import 'package:sky/framework/components/icon.dart'; | 9 import 'package:sky/framework/components/icon.dart'; |
| 10 import 'package:sky/framework/components/icon_button.dart'; |
| 10 import 'package:sky/framework/components/input.dart'; | 11 import 'package:sky/framework/components/input.dart'; |
| 11 import 'package:sky/framework/components/menu_divider.dart'; | 12 import 'package:sky/framework/components/menu_divider.dart'; |
| 12 import 'package:sky/framework/components/menu_item.dart'; | 13 import 'package:sky/framework/components/menu_item.dart'; |
| 13 import 'package:sky/framework/components/popup_menu.dart'; | 14 import 'package:sky/framework/components/popup_menu.dart'; |
| 14 import 'package:sky/framework/components/scaffold.dart'; | 15 import 'package:sky/framework/components/scaffold.dart'; |
| 15 import 'package:sky/framework/debug/tracing.dart'; | 16 import 'package:sky/framework/debug/tracing.dart'; |
| 16 import 'package:sky/framework/fn.dart'; | 17 import 'package:sky/framework/fn.dart'; |
| 17 import 'package:sky/framework/theme/typography.dart' as typography; | 18 import 'package:sky/framework/theme/typography.dart' as typography; |
| 19 import 'package:sky/framework/theme/colors.dart'; |
| 18 import 'stock_data.dart'; | 20 import 'stock_data.dart'; |
| 19 import 'stock_list.dart'; | 21 import 'stock_list.dart'; |
| 20 import 'stock_menu.dart'; | 22 import 'stock_menu.dart'; |
| 21 | 23 |
| 22 class StocksApp extends App { | 24 class StocksApp extends App { |
| 23 | |
| 24 DrawerController _drawerController = new DrawerController(); | 25 DrawerController _drawerController = new DrawerController(); |
| 25 PopupMenuController _menuController; | 26 PopupMenuController _menuController; |
| 26 | 27 |
| 27 static Style _iconStyle = new Style(''' | 28 static final Style _actionBarStyle = new Style(''' |
| 28 padding: 8px;''' | 29 background-color: ${Purple[500]};'''); |
| 29 ); | |
| 30 | 30 |
| 31 static Style _titleStyle = new Style(''' | 31 static final Style _searchBarStyle = new Style(''' |
| 32 padding-left: 24px; | 32 background-color: ${Grey[50]};'''); |
| 33 flex: 1; | 33 |
| 34 ${typography.white.title};''' | 34 static final Style _titleStyle = new Style(''' |
| 35 ); | 35 ${typography.white.title};'''); |
| 36 | 36 |
| 37 StockDataFetcher _stockDataFetcher; | 37 StockDataFetcher _stockDataFetcher; |
| 38 List<Stock> _stocks = []; | 38 List<Stock> _stocks = []; |
| 39 bool _isSearching = false; | 39 bool _isSearching = false; |
| 40 bool _isShowingMenu = false; | 40 bool _isShowingMenu = false; |
| 41 String _searchQuery; | 41 String _searchQuery; |
| 42 | 42 |
| 43 StocksApp() : super() { | 43 StocksApp() : super() { |
| 44 _stockDataFetcher = new StockDataFetcher((StockData data) { | 44 _stockDataFetcher = new StockDataFetcher((StockData data) { |
| 45 setState(() { | 45 setState(() { |
| 46 data.appendTo(_stocks); | 46 data.appendTo(_stocks); |
| 47 }); | 47 }); |
| 48 }); | 48 }); |
| 49 } | 49 } |
| 50 | 50 |
| 51 void _handleSearchClick(_) { | 51 void _handleSearchBegin(_) { |
| 52 setState(() { | 52 setState(() { |
| 53 _isSearching = !_isSearching; | 53 _isSearching = true; |
| 54 }); | 54 }); |
| 55 } | 55 } |
| 56 | 56 |
| 57 void _handleMenuClick(_) { | 57 void _handleSearchEnd(_) { |
| 58 setState(() { | 58 setState(() { |
| 59 _menuController = new PopupMenuController(); | 59 _isSearching = false; |
| 60 _menuController.open(); | 60 _searchQuery = null; |
| 61 }); | 61 }); |
| 62 } | 62 } |
| 63 | 63 |
| 64 void _handleSearchQueryChanged(query) { | 64 void _handleSearchQueryChanged(query) { |
| 65 setState(() { | 65 setState(() { |
| 66 _searchQuery = query; | 66 _searchQuery = query; |
| 67 }); | 67 }); |
| 68 } | 68 } |
| 69 | 69 |
| 70 Node build() { | 70 void _handleMenuClick(_) { |
| 71 var drawer = new Drawer( | 71 setState(() { |
| 72 _menuController = new PopupMenuController(); |
| 73 _menuController.open(); |
| 74 }); |
| 75 } |
| 76 |
| 77 Drawer buildDrawer() { |
| 78 return new Drawer( |
| 72 controller: _drawerController, | 79 controller: _drawerController, |
| 73 level: 3, | 80 level: 3, |
| 74 children: [ | 81 children: [ |
| 75 new DrawerHeader( | 82 new DrawerHeader(children: [new Text('Stocks')]), |
| 76 children: [new Text('Stocks')] | |
| 77 ), | |
| 78 new MenuItem( | 83 new MenuItem( |
| 79 key: 'Inbox', | 84 key: 'Inbox', |
| 80 icon: 'content/inbox', | 85 icon: 'content/inbox', |
| 81 children: [new Text('Inbox')] | 86 children: [new Text('Inbox')]), |
| 82 ), | 87 new MenuDivider(), |
| 83 new MenuDivider( | |
| 84 ), | |
| 85 new MenuItem( | 88 new MenuItem( |
| 86 key: 'Drafts', | 89 key: 'Drafts', |
| 87 icon: 'content/drafts', | 90 icon: 'content/drafts', |
| 88 children: [new Text('Drafts')] | 91 children: [new Text('Drafts')]), |
| 89 ), | |
| 90 new MenuItem( | 92 new MenuItem( |
| 91 key: 'Settings', | 93 key: 'Settings', |
| 92 icon: 'action/settings', | 94 icon: 'action/settings', |
| 93 children: [new Text('Settings')] | 95 children: [new Text('Settings')]), |
| 94 ), | |
| 95 new MenuItem( | 96 new MenuItem( |
| 96 key: 'Help & Feedback', | 97 key: 'Help & Feedback', |
| 97 icon: 'action/help', | 98 icon: 'action/help', |
| 98 children: [new Text('Help & Feedback')] | 99 children: [new Text('Help & Feedback')]) |
| 99 ) | |
| 100 ] | 100 ] |
| 101 ); | 101 ); |
| 102 } |
| 102 | 103 |
| 103 Node title; | 104 Node buildActionBar() { |
| 104 if (_isSearching) { | 105 return new StyleNode( |
| 105 title = new Input(focused: true, placeholder: 'Search stocks', | 106 new ActionBar( |
| 106 onChanged: _handleSearchQueryChanged); | 107 left: new IconButton( |
| 107 } else { | 108 icon: 'navigation/menu_white', |
| 108 title = new Text('Stocks'); | 109 onGestureTap: _drawerController.toggle), |
| 109 } | 110 center: new Container( |
| 111 style: _titleStyle, |
| 112 children: [new Text('Stocks')]), |
| 113 right: [ |
| 114 new IconButton( |
| 115 icon: 'action/search_white', |
| 116 onGestureTap: _handleSearchBegin), |
| 117 new IconButton( |
| 118 icon: 'navigation/more_vert_white', |
| 119 onGestureTap: _handleMenuClick) |
| 120 ]), |
| 121 _actionBarStyle); |
| 122 } |
| 110 | 123 |
| 111 var actionBar = new ActionBar( | 124 // TODO(abarth): Should we factor this into a SearchBar in the framework? |
| 112 children: [ | 125 Node buildSearchBar() { |
| 113 new EventTarget( | 126 return new StyleNode( |
| 114 new Icon(key: 'menu', style: _iconStyle, | 127 new ActionBar( |
| 115 size: 24, | 128 left: new IconButton( |
| 116 type: 'navigation/menu_white'), | 129 icon: 'navigation/arrow_back_grey600', |
| 117 onGestureTap: _drawerController.toggle | 130 onGestureTap: _handleSearchEnd), |
| 118 ), | 131 center: new Input( |
| 119 new Container( | 132 focused: true, |
| 120 style: _titleStyle, | 133 placeholder: 'Search stocks', |
| 121 children: [title] | 134 onChanged: _handleSearchQueryChanged)), |
| 122 ), | 135 _searchBarStyle); |
| 123 new EventTarget( | 136 } |
| 124 new Icon(key: 'search', style: _iconStyle, | |
| 125 size: 24, | |
| 126 type: 'action/search_white'), | |
| 127 onGestureTap: _handleSearchClick | |
| 128 ), | |
| 129 new EventTarget( | |
| 130 new Icon(key: 'more_white', style: _iconStyle, | |
| 131 size: 24, | |
| 132 type: 'navigation/more_vert_white'), | |
| 133 onGestureTap: _handleMenuClick | |
| 134 ) | |
| 135 ] | |
| 136 ); | |
| 137 | 137 |
| 138 Node build() { |
| 138 List<Node> overlays = []; | 139 List<Node> overlays = []; |
| 139 | 140 |
| 140 if (_menuController != null) { | 141 if (_menuController != null) { |
| 141 overlays.add(new EventTarget( | 142 overlays.add(new EventTarget( |
| 142 new StockMenu(controller: _menuController), | 143 new StockMenu(controller: _menuController), |
| 143 onGestureTap: (_) { | 144 onGestureTap: (_) { |
| 144 // TODO(abarth): We should close the menu when you tap away from the | 145 // TODO(abarth): We should close the menu when you tap away from the |
| 145 // menu rather than when you tap on the menu. | 146 // menu rather than when you tap on the menu. |
| 146 setState(() { | 147 setState(() { |
| 147 _menuController.close(); | 148 _menuController.close(); |
| 148 _menuController = null; | 149 _menuController = null; |
| 149 }); | 150 }); |
| 150 } | 151 } |
| 151 )); | 152 )); |
| 152 } | 153 } |
| 153 | 154 |
| 154 return new Scaffold( | 155 return new Scaffold( |
| 155 actionBar: actionBar, | 156 header: _isSearching ? buildSearchBar() : buildActionBar(), |
| 156 content: new Stocklist(stocks: _stocks, query: _searchQuery), | 157 content: new Stocklist(stocks: _stocks, query: _searchQuery), |
| 157 fab: new FloatingActionButton( | 158 fab: new FloatingActionButton( |
| 158 content: new Icon(type: 'content/add_white', size: 24), level: 3), | 159 content: new Icon(type: 'content/add_white', size: 24), level: 3), |
| 159 drawer: drawer, | 160 drawer: buildDrawer(), |
| 160 overlays: overlays | 161 overlays: overlays |
| 161 ); | 162 ); |
| 162 } | 163 } |
| 163 } | 164 } |
| OLD | NEW |