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 |