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 'dart:math' as math; | 5 import 'dart:math' as math; |
6 import 'dart:sky' as sky; | |
7 | 6 |
8 import 'package:sky/painting/text_style.dart'; | |
9 import 'package:sky/rendering/box.dart'; | 7 import 'package:sky/rendering/box.dart'; |
10 import 'package:sky/rendering/object.dart'; | 8 import 'package:sky/rendering/object.dart'; |
11 import 'package:sky/theme/colors.dart'; | |
12 import 'package:sky/widgets/basic.dart'; | 9 import 'package:sky/widgets/basic.dart'; |
13 import 'package:sky/widgets/icon.dart'; | 10 import 'package:sky/widgets/icon.dart'; |
14 import 'package:sky/widgets/ink_well.dart'; | 11 import 'package:sky/widgets/ink_well.dart'; |
| 12 import 'package:sky/widgets/theme.dart'; |
15 import 'package:sky/widgets/widget.dart'; | 13 import 'package:sky/widgets/widget.dart'; |
16 | 14 |
17 typedef void SelectedIndexChanged(int selectedIndex); | 15 typedef void SelectedIndexChanged(int selectedIndex); |
18 | 16 |
19 const double _kTabHeight = 46.0; | 17 const double _kTabHeight = 46.0; |
20 const double _kTabIndicatorHeight = 2.0; | 18 const double _kTabIndicatorHeight = 2.0; |
21 const double _kTabBarHeight = _kTabHeight + _kTabIndicatorHeight; | 19 const double _kTabBarHeight = _kTabHeight + _kTabIndicatorHeight; |
22 const double _kMinTabWidth = 72.0; | 20 const double _kMinTabWidth = 72.0; |
| 21 const int _kTabIconSize = 24; |
23 | 22 |
24 class TabBarParentData extends BoxParentData with | 23 class TabBarParentData extends BoxParentData with |
25 ContainerParentDataMixin<RenderBox> { } | 24 ContainerParentDataMixin<RenderBox> { } |
26 | 25 |
27 class RenderTabBar extends RenderBox with | 26 class RenderTabBar extends RenderBox with |
28 ContainerRenderObjectMixin<RenderBox, TabBarParentData>, | 27 ContainerRenderObjectMixin<RenderBox, TabBarParentData>, |
29 RenderBoxContainerDefaultsMixin<RenderBox, TabBarParentData> { | 28 RenderBoxContainerDefaultsMixin<RenderBox, TabBarParentData> { |
30 | 29 |
31 int _selectedIndex; | 30 int _selectedIndex; |
32 int get selectedIndex => _selectedIndex; | 31 int get selectedIndex => _selectedIndex; |
33 void set selectedIndex(int value) { | 32 void set selectedIndex(int value) { |
34 if (_selectedIndex != value) { | 33 if (_selectedIndex != value) { |
35 _selectedIndex = value; | 34 _selectedIndex = value; |
36 markNeedsPaint(); | 35 markNeedsPaint(); |
37 } | 36 } |
38 } | 37 } |
39 | 38 |
40 void setParentData(RenderBox child) { | 39 Color _backgroundColor; |
| 40 Color get backgroundColor => _backgroundColor; |
| 41 void set backgroundColor(Color value) { |
| 42 if (_backgroundColor != value) { |
| 43 _backgroundColor = value; |
| 44 markNeedsPaint(); |
| 45 } |
| 46 } |
| 47 |
| 48 Color _indicatorColor; |
| 49 Color get indicatorColor => _indicatorColor; |
| 50 void set indicatorColor(Color value) { |
| 51 if (_indicatorColor != value) { |
| 52 _indicatorColor = value; |
| 53 markNeedsPaint(); |
| 54 } |
| 55 } |
| 56 |
| 57 void setupParentData(RenderBox child) { |
41 if (child.parentData is! TabBarParentData) | 58 if (child.parentData is! TabBarParentData) |
42 child.parentData = new TabBarParentData(); | 59 child.parentData = new TabBarParentData(); |
43 } | 60 } |
44 | 61 |
45 double getMinIntrinsicWidth(BoxConstraints constraints) { | 62 double getMinIntrinsicWidth(BoxConstraints constraints) { |
46 BoxConstraints widthConstraints = | 63 BoxConstraints widthConstraints = |
47 new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraint
s.maxHeight); | 64 new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraint
s.maxHeight); |
48 double maxWidth = 0.0; | 65 double maxWidth = 0.0; |
49 int childCount = 0; | 66 int childCount = 0; |
50 RenderBox child = firstChild; | 67 RenderBox child = firstChild; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 x += tabWidth; | 129 x += tabWidth; |
113 child = child.parentData.nextSibling; | 130 child = child.parentData.nextSibling; |
114 } | 131 } |
115 } | 132 } |
116 | 133 |
117 void hitTestChildren(HitTestResult result, { Point position }) { | 134 void hitTestChildren(HitTestResult result, { Point position }) { |
118 defaultHitTestChildren(result, position: position); | 135 defaultHitTestChildren(result, position: position); |
119 } | 136 } |
120 | 137 |
121 void _paintIndicator(RenderCanvas canvas, RenderBox selectedTab) { | 138 void _paintIndicator(RenderCanvas canvas, RenderBox selectedTab) { |
| 139 if (indicatorColor == null) |
| 140 return; |
| 141 |
122 var size = new Size(selectedTab.size.width, _kTabIndicatorHeight); | 142 var size = new Size(selectedTab.size.width, _kTabIndicatorHeight); |
123 var point = new Point(selectedTab.parentData.position.x, _kTabHeight); | 143 var point = new Point(selectedTab.parentData.position.x, _kTabHeight); |
124 Rect rect = new Rect.fromPointAndSize(point, size); | 144 Rect rect = new Rect.fromPointAndSize(point, size); |
125 // TODO(hansmuller): indicator color should be based on the theme. | 145 canvas.drawRect(rect, new Paint()..color = indicatorColor); |
126 canvas.drawRect(rect, new Paint()..color = White); | |
127 } | 146 } |
128 | 147 |
129 void paint(RenderCanvas canvas) { | 148 void paint(RenderCanvas canvas) { |
130 Rect rect = new Rect.fromSize(size); | 149 if (backgroundColor != null) { |
131 canvas.drawRect(rect, new Paint()..color = Blue[500]); | 150 Rect rect = new Rect.fromSize(size); |
| 151 canvas.drawRect(rect, new Paint()..color = backgroundColor); |
| 152 } |
132 | 153 |
133 int index = 0; | 154 int index = 0; |
134 RenderBox child = firstChild; | 155 RenderBox child = firstChild; |
135 while (child != null) { | 156 while (child != null) { |
136 assert(child.parentData is TabBarParentData); | 157 assert(child.parentData is TabBarParentData); |
137 canvas.paintChild(child, child.parentData.position); | 158 canvas.paintChild(child, child.parentData.position); |
138 if (index++ == selectedIndex) | 159 if (index++ == selectedIndex) |
139 _paintIndicator(canvas, child); | 160 _paintIndicator(canvas, child); |
140 child = child.parentData.nextSibling; | 161 child = child.parentData.nextSibling; |
141 } | 162 } |
142 } | 163 } |
143 } | 164 } |
144 | 165 |
145 class TabBarWrapper extends MultiChildRenderObjectWrapper { | 166 class TabBarWrapper extends MultiChildRenderObjectWrapper { |
146 TabBarWrapper(List<Widget> children, this.selectedIndex, { String key }) | 167 TabBarWrapper({ |
147 : super(key: key, children: children); | 168 List<Widget> children, |
| 169 this.selectedIndex, |
| 170 this.backgroundColor, |
| 171 this.indicatorColor, |
| 172 String key |
| 173 }) : super(key: key, children: children); |
148 | 174 |
149 final int selectedIndex; | 175 final int selectedIndex; |
| 176 final Color backgroundColor; |
| 177 final Color indicatorColor; |
150 | 178 |
151 RenderTabBar get root => super.root; | 179 RenderTabBar get root => super.root; |
152 RenderTabBar createNode() => new RenderTabBar(); | 180 RenderTabBar createNode() => new RenderTabBar(); |
153 | 181 |
154 void syncRenderObject(Widget old) { | 182 void syncRenderObject(Widget old) { |
155 super.syncRenderObject(old); | 183 super.syncRenderObject(old); |
156 root.selectedIndex = selectedIndex; | 184 root.selectedIndex = selectedIndex; |
| 185 root.backgroundColor = backgroundColor; |
| 186 root.indicatorColor = indicatorColor; |
157 } | 187 } |
158 } | 188 } |
159 | 189 |
160 class TabLabel { | 190 class TabLabel { |
161 const TabLabel({ this.text, this.icon }); | 191 const TabLabel({ this.text, this.icon }); |
162 | 192 |
163 final String text; | 193 final String text; |
164 final String icon; | 194 final String icon; |
165 } | 195 } |
166 | 196 |
167 class Tab extends Component { | 197 class Tab extends Component { |
168 Tab({ | 198 Tab({ |
169 String key, | 199 String key, |
170 this.label, | 200 this.label, |
171 this.selected: false | 201 this.selected: false |
172 }) : super(key: key) { | 202 }) : super(key: key) { |
173 assert(label.text != null || label.icon != null); | 203 assert(label.text != null || label.icon != null); |
174 } | 204 } |
175 | 205 |
176 final TabLabel label; | 206 final TabLabel label; |
177 final bool selected; | 207 final bool selected; |
178 | 208 |
179 // TODO(hansmuller): use themes here. | |
180 static const TextStyle selectedStyle = const TextStyle(color: const Color(0xFF
FFFFFF)); | |
181 static const TextStyle style = const TextStyle(color: const Color(0xB2FFFFFF))
; | |
182 | |
183 Widget _buildLabelText() { | 209 Widget _buildLabelText() { |
184 assert(label.text != null); | 210 assert(label.text != null); |
185 return new Text(label.text, style: style); | 211 return new Text(label.text, style: Theme.of(this).toolbarText.button); |
186 } | 212 } |
187 | 213 |
188 Widget _buildLabelIcon() { | 214 Widget _buildLabelIcon() { |
189 assert(label.icon != null); | 215 assert(label.icon != null); |
190 return new Icon(type: label.icon, size: 24); | 216 return new Icon(type: label.icon, size: _kTabIconSize); |
191 } | 217 } |
192 | 218 |
193 Widget build() { | 219 Widget build() { |
194 Widget labelContents; | 220 Widget labelContents; |
195 if (label.icon == null) { | 221 if (label.icon == null) { |
196 labelContents = _buildLabelText(); | 222 labelContents = _buildLabelText(); |
197 } else if (label.text == null) { | 223 } else if (label.text == null) { |
198 labelContents = _buildLabelIcon(); | 224 labelContents = _buildLabelIcon(); |
199 } else { | 225 } else { |
200 labelContents = new Flex( | 226 labelContents = new Flex( |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 onGestureTap: (_) => _handleTap(tabIndex) | 273 onGestureTap: (_) => _handleTap(tabIndex) |
248 ); | 274 ); |
249 } | 275 } |
250 | 276 |
251 Widget build() { | 277 Widget build() { |
252 assert(labels != null && labels.isNotEmpty); | 278 assert(labels != null && labels.isNotEmpty); |
253 List<Widget> tabs = <Widget>[]; | 279 List<Widget> tabs = <Widget>[]; |
254 for (int tabIndex = 0; tabIndex < labels.length; tabIndex++) { | 280 for (int tabIndex = 0; tabIndex < labels.length; tabIndex++) { |
255 tabs.add(_toTab(labels[tabIndex], tabIndex)); | 281 tabs.add(_toTab(labels[tabIndex], tabIndex)); |
256 } | 282 } |
257 return new TabBarWrapper(tabs, selectedIndex); | 283 return new TabBarWrapper( |
| 284 children: tabs, |
| 285 selectedIndex: selectedIndex, |
| 286 backgroundColor: Theme.of(this).primary[500], |
| 287 indicatorColor: Theme.of(this).accent[200] |
| 288 ); |
258 } | 289 } |
259 } | 290 } |
260 | 291 |
261 | 292 |
OLD | NEW |