| 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 |