diff --git a/sdk/example/widgets/tabs.dart b/sdk/example/widgets/tabs.dart index 93d259caa394eaedd19373338c265059f32cc442..4b69a6a4e5955a1de2e42189aa66d8fc7153f6ca 100644 --- a/sdk/example/widgets/tabs.dart +++ b/sdk/example/widgets/tabs.dart @@ -14,12 +14,13 @@ import 'package:sky/widgets/widget.dart'; class TabbedNavigatorApp extends App { // The index of the selected tab for each of the TabNavigators constructed below. - List selectedIndices = new List.filled(4, 0); + List selectedIndices = new List.filled(5, 0); - TabNavigator _buildTabNavigator(int n, List views) { + TabNavigator _buildTabNavigator(int n, List views, {scrollable: false}) { return new TabNavigator( views: views, selectedIndex: selectedIndices[n], + scrollable: scrollable, onChanged: (tabIndex) { setState(() { selectedIndices[n] = tabIndex; } ); } @@ -72,9 +73,32 @@ class TabbedNavigatorApp extends App { return _buildTabNavigator(n, views); } + TabNavigator _buildScrollableTabNavigator(int n) { + Iterable views = [ + "MIN WIDTH", + "THIS TAB LABEL IS SO WIDE THAT IT OCCUPIES TWO LINES", + "THIS TAB IS PRETTY WIDE TOO", + "MORE", + "TABS", + "TO", + "STRETCH", + "OUT", + "THE", + "TAB BAR" + ] + .map((text) { + return new TabNavigatorView( + label: new TabLabel(text: text), + builder: () => _buildContent(text) + ); + }); + return _buildTabNavigator(n, views.toList(), scrollable: true); + } + + Container _buildCard(TabNavigator tabNavigator) { return new Container( - child: new Card(child: tabNavigator), + child: new Card(child: new Padding(child: tabNavigator, padding: const EdgeDims.all(8.0))), padding: const EdgeDims.all(12.0), decoration: new BoxDecoration(backgroundColor: Theme.of(this).primarySwatch[50]) ); @@ -93,10 +117,15 @@ class TabbedNavigatorApp extends App { new TabNavigatorView( label: const TabLabel(text: 'BOTH'), builder: () => _buildCard(_buildTextAndIconLabelsTabNavigator(2)) + ), + new TabNavigatorView( + label: const TabLabel(text: 'SCROLL'), + builder: () => _buildCard(_buildScrollableTabNavigator(3)) ) ]; - TabNavigator tabNavigator = _buildTabNavigator(3, views); + TabNavigator tabNavigator = _buildTabNavigator(4, views); + assert(selectedIndices.length == 5); ToolBar toolbar = new ToolBar( center: new Text('Tabbed Navigator', style: typography.white.title) diff --git a/sdk/lib/widgets/scrollable.dart b/sdk/lib/widgets/scrollable.dart index a6c4023a356507f47251fd4354077a9ef3b1ee9c..34e1e07e1eafe0017bba18bea7301954a47a3f1a 100644 --- a/sdk/lib/widgets/scrollable.dart +++ b/sdk/lib/widgets/scrollable.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:math' as math; import 'dart:sky' as sky; import '../animation/generators.dart'; @@ -14,24 +13,31 @@ import 'material.dart'; const double _kMillisecondsPerSecond = 1000.0; -double _velocityForFlingGesture(sky.GestureEvent event) { - return math.max(-config.kMaxFlingVelocity, math.min(config.kMaxFlingVelocity, - -event.velocityY)) / _kMillisecondsPerSecond; +double _velocityForFlingGesture(double eventVelocity) { + return eventVelocity.clamp(-config.kMaxFlingVelocity, config.kMaxFlingVelocity) / + _kMillisecondsPerSecond; } abstract class ScrollClient { bool ancestorScrolled(Scrollable ancestor); } +enum ScrollDirection { vertical, horizontal } + abstract class Scrollable extends Component { - Scrollable({ String key, Color this.backgroundColor }) - : super(key: key, stateful: true); + Scrollable({ + String key, + this.backgroundColor, + this.direction: ScrollDirection.vertical + }) : super(key: key, stateful: true); Color backgroundColor; + ScrollDirection direction; void syncFields(Scrollable source) { backgroundColor = source.backgroundColor; + direction == source.direction; } double _scrollOffset = 0.0; @@ -145,11 +151,14 @@ abstract class Scrollable extends Component { } void _handleScrollUpdate(sky.GestureEvent event) { - scrollBy(-event.dy); + scrollBy(direction == ScrollDirection.horizontal ? event.dx : -event.dy); } void _handleFlingStart(sky.GestureEvent event) { - _startSimulation(_createParticle(_velocityForFlingGesture(event))); + double eventVelocity = direction == ScrollDirection.horizontal + ? -event.velocityX + : -event.velocityY; + _startSimulation(_createParticle(_velocityForFlingGesture(eventVelocity))); } void _handleFlingCancel(sky.GestureEvent event) { diff --git a/sdk/lib/widgets/tabs.dart b/sdk/lib/widgets/tabs.dart index f621ff2069bd6bac44b587de8249e364225b7e65..6123888511fc371a0b71dc20618501bd569dcbee 100644 --- a/sdk/lib/widgets/tabs.dart +++ b/sdk/lib/widgets/tabs.dart @@ -4,20 +4,30 @@ import 'dart:math' as math; +import 'package:sky/animation/scroll_behavior.dart'; +import 'package:sky/painting/text_style.dart'; import 'package:sky/rendering/box.dart'; import 'package:sky/rendering/object.dart'; +import 'package:vector_math/vector_math.dart'; import 'package:sky/widgets/basic.dart'; import 'package:sky/widgets/icon.dart'; import 'package:sky/widgets/ink_well.dart'; +import 'package:sky/widgets/scrollable.dart'; import 'package:sky/widgets/theme.dart'; import 'package:sky/widgets/widget.dart'; typedef void SelectedIndexChanged(int selectedIndex); +typedef void LayoutChanged(Size size, List widths); +// See https://www.google.com/design/spec/components/tabs.html#tabs-specs const double _kTabHeight = 46.0; const double _kTextAndIconTabHeight = 72.0; const double _kTabIndicatorHeight = 2.0; const double _kMinTabWidth = 72.0; +const double _kMaxTabWidth = 264.0; +const double _kRelativeMaxTabWidth = 56.0; +const EdgeDims _kTabLabelPadding = const EdgeDims.symmetric(horizontal: 12.0); +const TextStyle _kTabTextStyle = const TextStyle(textAlign: TextAlign.center); const int _kTabIconSize = 24; class TabBarParentData extends BoxParentData with @@ -27,6 +37,8 @@ class RenderTabBar extends RenderBox with ContainerRenderObjectMixin, RenderBoxContainerDefaultsMixin { + RenderTabBar(this.onLayoutChanged); + int _selectedIndex; int get selectedIndex => _selectedIndex; void set selectedIndex(int value) { @@ -63,6 +75,15 @@ class RenderTabBar extends RenderBox with } } + bool _scrollable; + bool get scrollable => _scrollable; + void set scrollable(bool value) { + if (_scrollable != value) { + _scrollable = value; + markNeedsLayout(); + } + } + void setupParentData(RenderBox child) { if (child.parentData is! TabBarParentData) child.parentData = new TabBarParentData(); @@ -71,6 +92,7 @@ class RenderTabBar extends RenderBox with double getMinIntrinsicWidth(BoxConstraints constraints) { BoxConstraints widthConstraints = new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraints.maxHeight); + double maxWidth = 0.0; RenderBox child = firstChild; while (child != null) { @@ -78,12 +100,14 @@ class RenderTabBar extends RenderBox with assert(child.parentData is TabBarParentData); child = child.parentData.nextSibling; } - return constraints.constrainWidth(maxWidth * childCount); + double width = scrollable ? maxWidth : maxWidth * childCount; + return constraints.constrainWidth(width); } double getMaxIntrinsicWidth(BoxConstraints constraints) { BoxConstraints widthConstraints = new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraints.maxHeight); + double maxWidth = 0.0; RenderBox child = firstChild; while (child != null) { @@ -91,7 +115,8 @@ class RenderTabBar extends RenderBox with assert(child.parentData is TabBarParentData); child = child.parentData.nextSibling; } - return constraints.constrainWidth(maxWidth * childCount); + double width = scrollable ? maxWidth : maxWidth * childCount; + return constraints.constrainWidth(width); } double get _tabBarHeight { @@ -104,15 +129,7 @@ class RenderTabBar extends RenderBox with double getMaxIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeight(constraints); - void performLayout() { - assert(constraints is BoxConstraints); - - size = constraints.constrain(new Size(constraints.maxWidth, _tabBarHeight)); - assert(!size.isInfinite); - - if (childCount == 0) - return; - + void layoutFixedWidthTabs() { double tabWidth = size.width / childCount; BoxConstraints tabConstraints = new BoxConstraints.tightFor(width: tabWidth, height: size.height); @@ -127,6 +144,67 @@ class RenderTabBar extends RenderBox with } } + void layoutScrollableTabs() { + BoxConstraints tabConstraints = new BoxConstraints( + minWidth: _kMinTabWidth, + maxWidth: math.min(size.width - _kRelativeMaxTabWidth, _kMaxTabWidth), + minHeight: size.height, + maxHeight: size.height); + double x = 0.0; + RenderBox child = firstChild; + while (child != null) { + child.layout(tabConstraints, parentUsesSize: true); + assert(child.parentData is TabBarParentData); + child.parentData.position = new Point(x, 0.0); + x += child.size.width; + child = child.parentData.nextSibling; + } + } + + Size layoutSize; + List layoutWidths; + LayoutChanged onLayoutChanged; + + void reportLayoutChangedIfNeeded() { + assert(onLayoutChanged != null); + List widths = new List(childCount); + if (!scrollable && childCount > 0) { + double tabWidth = size.width / childCount; + widths.fillRange(0, widths.length - 1, tabWidth); + } else if (scrollable) { + RenderBox child = firstChild; + int childIndex = 0; + while (child != null) { + widths[childIndex++] = child.size.width; + child = child.parentData.nextSibling; + } + assert(childIndex == widths.length); + } + if (size != layoutSize || widths != layoutWidths) { + layoutSize = size; + layoutWidths = widths; + onLayoutChanged(layoutSize, layoutWidths); + } + } + + void performLayout() { + assert(constraints is BoxConstraints); + + size = constraints.constrain(new Size(constraints.maxWidth, _tabBarHeight)); + assert(!size.isInfinite); + + if (childCount == 0) + return; + + if (scrollable) + layoutScrollableTabs(); + else + layoutFixedWidthTabs(); + + if (onLayoutChanged != null) + reportLayoutChangedIfNeeded(); + } + void hitTestChildren(HitTestResult result, { Point position }) { defaultHitTestChildren(result, position: position); } @@ -146,7 +224,10 @@ class RenderTabBar extends RenderBox with void paint(PaintingCanvas canvas, Offset offset) { if (backgroundColor != null) { - Rect rect = offset & size; + double width = layoutWidths != null + ? layoutWidths.reduce((sum, width) => sum + width) + : size.width; + Rect rect = offset & new Size(width, size.height); canvas.drawRect(rect, new Paint()..color = backgroundColor); } @@ -169,6 +250,8 @@ class TabBarWrapper extends MultiChildRenderObjectWrapper { this.backgroundColor, this.indicatorColor, this.textAndIcons, + this.scrollable: false, + this.onLayoutChanged, String key }) : super(key: key, children: children); @@ -176,9 +259,11 @@ class TabBarWrapper extends MultiChildRenderObjectWrapper { final Color backgroundColor; final Color indicatorColor; final bool textAndIcons; + final bool scrollable; + final LayoutChanged onLayoutChanged; RenderTabBar get root => super.root; - RenderTabBar createNode() => new RenderTabBar(); + RenderTabBar createNode() => new RenderTabBar(onLayoutChanged); void syncRenderObject(Widget old) { super.syncRenderObject(old); @@ -186,6 +271,8 @@ class TabBarWrapper extends MultiChildRenderObjectWrapper { root.backgroundColor = backgroundColor; root.indicatorColor = indicatorColor; root.textAndIcons = textAndIcons; + root.scrollable = scrollable; + root.onLayoutChanged = onLayoutChanged; } } @@ -210,7 +297,8 @@ class Tab extends Component { Widget _buildLabelText() { assert(label.text != null); - return new Text(label.text, style: Theme.of(this).toolbarText.button); + TextStyle textStyle = Theme.of(this).toolbarText.button.merge(_kTabTextStyle); + return new Text(label.text, style: textStyle); } Widget _buildLabelIcon() { @@ -246,24 +334,40 @@ class Tab extends Component { Container centeredLabel = new Container( child: new Center(child: highlightedLabel), - constraints: new BoxConstraints(minWidth: _kMinTabWidth) + constraints: new BoxConstraints(minWidth: _kMinTabWidth), + padding: _kTabLabelPadding ); return new InkWell(child: centeredLabel); } } -class TabBar extends Component { +class TabBar extends Scrollable { TabBar({ String key, this.labels, this.selectedIndex: 0, - this.onChanged - }) : super(key: key); + this.onChanged, + this.scrollable: false + }) : super(key: key, direction: ScrollDirection.horizontal); + + Iterable labels; + int selectedIndex; + SelectedIndexChanged onChanged; + bool scrollable; + + void syncFields(TabBar source) { + super.syncFields(source); + labels = source.labels; + selectedIndex = source.selectedIndex; + onChanged = source.onChanged; + scrollable = source.scrollable; + if (!scrollable) + scrollTo(0.0); + } - final Iterable labels; - final int selectedIndex; - final SelectedIndexChanged onChanged; + ScrollBehavior createScrollBehavior() => new BoundedScrollBehavior(); + BoundedScrollBehavior get scrollBehavior => super.scrollBehavior; void _handleTap(int tabIndex) { if (tabIndex != selectedIndex && onChanged != null) @@ -282,7 +386,19 @@ class TabBar extends Component { ); } - Widget build() { + Size _tabBarSize; + List _tabWidths; + + void _layoutChanged(Size tabBarSize, List tabWidths) { + setState(() { + _tabBarSize = tabBarSize; + _tabWidths = tabWidths; + scrollBehavior.maxOffset = + _tabWidths.reduce((sum, width) => sum + width) - _tabBarSize.width; + }); + } + + Widget buildContent() { assert(labels != null && labels.isNotEmpty); List tabs = []; bool textAndIcons = false; @@ -292,13 +408,20 @@ class TabBar extends Component { if (label.text != null && label.icon != null) textAndIcons = true; } - return new TabBarWrapper( + + TabBarWrapper tabBarWrapper = new TabBarWrapper( children: tabs, selectedIndex: selectedIndex, backgroundColor: Theme.of(this).primaryColor, indicatorColor: Theme.of(this).accentColor, - textAndIcons: textAndIcons + textAndIcons: textAndIcons, + scrollable: scrollable, + onLayoutChanged: scrollable ? _layoutChanged : null ); + + Matrix4 transform = new Matrix4.identity(); + transform.translate(-scrollOffset, 0.0); + return new Transform(child: tabBarWrapper, transform: transform); } } @@ -321,12 +444,14 @@ class TabNavigator extends Component { String key, this.views, this.selectedIndex: 0, - this.onChanged + this.onChanged, + this.scrollable: false }) : super(key: key); final List views; final int selectedIndex; final SelectedIndexChanged onChanged; + final bool scrollable; void _handleSelectedIndexChanged(int tabIndex) { if (onChanged != null) @@ -340,7 +465,8 @@ class TabNavigator extends Component { TabBar tabBar = new TabBar( labels: views.map((view) => view.label), onChanged: _handleSelectedIndexChanged, - selectedIndex: selectedIndex + selectedIndex: selectedIndex, + scrollable: scrollable ); Widget content = views[selectedIndex].buildContent(); diff --git a/tests/examples/stocks-expected.txt b/tests/examples/stocks-expected.txt index 52d64de6b1cb19b10e4903f6cdaaed51987b5227..9787c1b1d032c21cc786c3b3593b325331cce302 100644 --- a/tests/examples/stocks-expected.txt +++ b/tests/examples/stocks-expected.txt @@ -12,24 +12,33 @@ PAINT FOR FRAME #2 ---------------------------------------------- 2 | | | TestPaintingCanvas() constructor: 800.0 x 600.0 2 | | | paintChild RenderFlex at Point(0.0, 81.0) 2 | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | paintChild RenderTabBar at Point(0.0, 81.0) +2 | | | | paintChild RenderDecoratedBox at Point(0.0, 81.0) 2 | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | drawRect(Rect.fromLTRB(0.0, 81.0, 800.0, 129.0), Paint(color:Color(0xff9c27b0))) -2 | | | | | paintChild RenderInkWell at Point(0.0, 81.0) +2 | | | | | drawRect(Rect.fromLTRB(0.0, 81.0, 800.0, 129.0), Paint(color:Color(0xfffafafa))) +2 | | | | | save +2 | | | | | translate(0.0, 81.0) +2 | | | | | concat([1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]) +2 | | | | | drawRect(Rect.fromLTRB(0.0, 0.0, 800.0, 48.0), Paint(color:Color(0xff9c27b0))) +2 | | | | | paintChild RenderInkWell at Point(0.0, 0.0) 2 | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | paintChild RenderOpacity at Point(174.5, 97.0) +2 | | | | | | paintChild RenderPositionedBox at Point(12.0, 0.0) 2 | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | translate(174.5, 97.0) -2 | | | | | | | translate(-174.5, -97.0) -2 | | | | | drawRect(Rect.fromLTRB(0.0, 127.0, 400.0, 129.0), Paint(color:Color(0xffff5252))) -2 | | | | | paintChild RenderInkWell at Point(400.0, 81.0) +2 | | | | | | | paintChild RenderOpacity at Point(171.0, 14.0) +2 | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | | translate(171.0, 14.0) +2 | | | | | | | | translate(-171.0, -14.0) +2 | | | | | drawRect(Rect.fromLTRB(0.0, 46.0, 400.0, 48.0), Paint(color:Color(0xffff5252))) +2 | | | | | paintChild RenderInkWell at Point(400.0, 0.0) 2 | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | paintChild RenderOpacity at Point(562.0, 97.0) +2 | | | | | | paintChild RenderPositionedBox at Point(412.0, 0.0) 2 | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) -2 | | | | | | | translate(562.0, 97.0) -2 | | | | | | | translate(-562.0, -97.0) -2 | | | | | | | restore +2 | | | | | | | paintChild RenderOpacity at Point(560.0, 14.0) +2 | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) +2 | | | | | | | | translate(560.0, 14.0) +2 | | | | | | | | translate(-560.0, -14.0) +2 | | | | | | | | restore +2 | | | | | restore 2 | | | | paintChild RenderDecoratedBox at Point(0.0, 129.0) 2 | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 2 | | | | | drawRect(Rect.fromLTRB(0.0, 129.0, 800.0, 600.0), Paint(color:Color(0xfffafafa))) @@ -83,24 +92,33 @@ PAINT FOR FRAME #3 ---------------------------------------------- 3 | | | TestPaintingCanvas() constructor: 800.0 x 600.0 3 | | | paintChild RenderFlex at Point(0.0, 81.0) 3 | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -3 | | | | paintChild RenderTabBar at Point(0.0, 81.0) +3 | | | | paintChild RenderDecoratedBox at Point(0.0, 81.0) 3 | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -3 | | | | | drawRect(Rect.fromLTRB(0.0, 81.0, 800.0, 129.0), Paint(color:Color(0xff9c27b0))) -3 | | | | | paintChild RenderInkWell at Point(0.0, 81.0) +3 | | | | | drawRect(Rect.fromLTRB(0.0, 81.0, 800.0, 129.0), Paint(color:Color(0xfffafafa))) +3 | | | | | save +3 | | | | | translate(0.0, 81.0) +3 | | | | | concat([1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]) +3 | | | | | drawRect(Rect.fromLTRB(0.0, 0.0, 800.0, 48.0), Paint(color:Color(0xff9c27b0))) +3 | | | | | paintChild RenderInkWell at Point(0.0, 0.0) 3 | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -3 | | | | | | paintChild RenderOpacity at Point(174.5, 97.0) +3 | | | | | | paintChild RenderPositionedBox at Point(12.0, 0.0) 3 | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -3 | | | | | | | translate(174.5, 97.0) -3 | | | | | | | translate(-174.5, -97.0) -3 | | | | | drawRect(Rect.fromLTRB(0.0, 127.0, 400.0, 129.0), Paint(color:Color(0xffff5252))) -3 | | | | | paintChild RenderInkWell at Point(400.0, 81.0) +3 | | | | | | | paintChild RenderOpacity at Point(171.0, 14.0) +3 | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +3 | | | | | | | | translate(171.0, 14.0) +3 | | | | | | | | translate(-171.0, -14.0) +3 | | | | | drawRect(Rect.fromLTRB(0.0, 46.0, 400.0, 48.0), Paint(color:Color(0xffff5252))) +3 | | | | | paintChild RenderInkWell at Point(400.0, 0.0) 3 | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -3 | | | | | | paintChild RenderOpacity at Point(562.0, 97.0) +3 | | | | | | paintChild RenderPositionedBox at Point(412.0, 0.0) 3 | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -3 | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) -3 | | | | | | | translate(562.0, 97.0) -3 | | | | | | | translate(-562.0, -97.0) -3 | | | | | | | restore +3 | | | | | | | paintChild RenderOpacity at Point(560.0, 14.0) +3 | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +3 | | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) +3 | | | | | | | | translate(560.0, 14.0) +3 | | | | | | | | translate(-560.0, -14.0) +3 | | | | | | | | restore +3 | | | | | restore 3 | | | | paintChild RenderDecoratedBox at Point(0.0, 129.0) 3 | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 3 | | | | | drawRect(Rect.fromLTRB(0.0, 129.0, 800.0, 600.0), Paint(color:Color(0xfffafafa))) diff --git a/tests/examples/tabs-expected.txt b/tests/examples/tabs-expected.txt index f8b71d62b68525aa9e37b41236e1a2d454e96d9e..f53969a27de0d09f5865b36ca7342fc450389a95 100644 --- a/tests/examples/tabs-expected.txt +++ b/tests/examples/tabs-expected.txt @@ -10,32 +10,53 @@ PAINT FOR FRAME #2 ---------------------------------------------- 2 | | TestPaintingCanvas() constructor: 800.0 x 600.0 2 | | paintChild RenderFlex at Point(0.0, 81.0) 2 | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | paintChild RenderTabBar at Point(0.0, 81.0) +2 | | | paintChild RenderDecoratedBox at Point(0.0, 81.0) 2 | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | drawRect(Rect.fromLTRB(0.0, 81.0, 800.0, 129.0), Paint(color:Color(0xff2196f3))) -2 | | | | paintChild RenderInkWell at Point(0.0, 81.0) +2 | | | | drawRect(Rect.fromLTRB(0.0, 81.0, 800.0, 129.0), Paint(color:Color(0xfffafafa))) +2 | | | | save +2 | | | | translate(0.0, 81.0) +2 | | | | concat([1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]) +2 | | | | drawRect(Rect.fromLTRB(0.0, 0.0, 800.0, 48.0), Paint(color:Color(0xff2196f3))) +2 | | | | paintChild RenderInkWell at Point(0.0, 0.0) 2 | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | paintChild RenderOpacity at Point(115.33333333333334, 97.0) +2 | | | | | paintChild RenderPositionedBox at Point(12.0, 0.0) 2 | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | translate(115.33333333333334, 97.0) -2 | | | | | | translate(-115.33333333333334, -97.0) -2 | | | | drawRect(Rect.fromLTRB(0.0, 127.0, 266.6666564941406, 129.0), Paint(color:Color(0xff2196f3))) -2 | | | | paintChild RenderInkWell at Point(266.6666666666667, 81.0) +2 | | | | | | paintChild RenderOpacity at Point(82.0, 14.0) +2 | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | translate(82.0, 14.0) +2 | | | | | | | translate(-82.0, -14.0) +2 | | | | drawRect(Rect.fromLTRB(0.0, 46.0, 200.0, 48.0), Paint(color:Color(0xff2196f3))) +2 | | | | paintChild RenderInkWell at Point(200.0, 0.0) 2 | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | paintChild RenderOpacity at Point(377.5, 97.0) +2 | | | | | paintChild RenderPositionedBox at Point(212.0, 0.0) 2 | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) -2 | | | | | | translate(377.5, 97.0) -2 | | | | | | translate(-377.5, -97.0) -2 | | | | | | restore -2 | | | | paintChild RenderInkWell at Point(533.3333333333334, 81.0) +2 | | | | | | paintChild RenderOpacity at Point(277.5, 14.0) +2 | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) +2 | | | | | | | translate(277.5, 14.0) +2 | | | | | | | translate(-277.5, -14.0) +2 | | | | | | | restore +2 | | | | paintChild RenderInkWell at Point(400.0, 0.0) 2 | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | paintChild RenderOpacity at Point(646.6666666666667, 97.0) +2 | | | | | paintChild RenderPositionedBox at Point(412.0, 0.0) 2 | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) -2 | | | | | | translate(646.6666666666667, 97.0) -2 | | | | | | translate(-646.6666666666667, -97.0) -2 | | | | | | restore +2 | | | | | | paintChild RenderOpacity at Point(480.0, 14.0) +2 | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) +2 | | | | | | | translate(480.0, 14.0) +2 | | | | | | | translate(-480.0, -14.0) +2 | | | | | | | restore +2 | | | | paintChild RenderInkWell at Point(600.0, 0.0) +2 | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | paintChild RenderPositionedBox at Point(612.0, 0.0) +2 | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | paintChild RenderOpacity at Point(672.0, 14.0) +2 | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) +2 | | | | | | | translate(672.0, 14.0) +2 | | | | | | | translate(-672.0, -14.0) +2 | | | | | | | restore +2 | | | | restore 2 | | | paintChild RenderDecoratedBox at Point(0.0, 129.0) 2 | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 2 | | | | drawRect(Rect.fromLTRB(0.0, 129.0, 800.0, 600.0), Paint(color:Color(0xffe3f2fd))) @@ -46,46 +67,61 @@ PAINT FOR FRAME #2 ---------------------------------------------- 2 | | | | | | drawRRect(Instance of 'RRect', Paint(color:Color(0xffffffff), drawLooper:true)) 2 | | | | | | saveLayer(Rect.fromLTRB(16.0, 145.0, 784.0, 584.0), Paint(color:Color(0xff000000))) 2 | | | | | | clipRRect() -2 | | | | | | paintChild RenderTabBar at Point(16.0, 145.0) +2 | | | | | | paintChild RenderFlex at Point(24.0, 153.0) 2 | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | drawRect(Rect.fromLTRB(16.0, 145.0, 784.0, 193.0), Paint(color:Color(0xff2196f3))) -2 | | | | | | | paintChild RenderInkWell at Point(16.0, 145.0) +2 | | | | | | | paintChild RenderDecoratedBox at Point(24.0, 153.0) 2 | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | | paintChild RenderOpacity at Point(96.5, 159.0) +2 | | | | | | | | drawRect(Rect.fromLTRB(24.0, 153.0, 776.0, 201.0), Paint(color:Color(0xfffafafa))) +2 | | | | | | | | save +2 | | | | | | | | translate(24.0, 153.0) +2 | | | | | | | | concat([1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]) +2 | | | | | | | | drawRect(Rect.fromLTRB(0.0, 0.0, 752.0, 48.0), Paint(color:Color(0xff2196f3))) +2 | | | | | | | | paintChild RenderInkWell at Point(0.0, 0.0) 2 | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | | | translate(96.5, 159.0) -2 | | | | | | | | | translate(-96.5, -159.0) -2 | | | | | | | drawRect(Rect.fromLTRB(16.0, 191.0, 208.0, 193.0), Paint(color:Color(0xff2196f3))) -2 | | | | | | | paintChild RenderInkWell at Point(208.0, 145.0) -2 | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | | paintChild RenderOpacity at Point(287.0, 159.0) +2 | | | | | | | | | paintChild RenderPositionedBox at Point(12.0, 0.0) +2 | | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | | | | paintChild RenderOpacity at Point(78.5, 14.0) +2 | | | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | | | | | translate(78.5, 14.0) +2 | | | | | | | | | | | translate(-78.5, -14.0) +2 | | | | | | | | drawRect(Rect.fromLTRB(0.0, 46.0, 188.0, 48.0), Paint(color:Color(0xff2196f3))) +2 | | | | | | | | paintChild RenderInkWell at Point(188.0, 0.0) 2 | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) -2 | | | | | | | | | translate(287.0, 159.0) -2 | | | | | | | | | translate(-287.0, -159.0) -2 | | | | | | | | | restore -2 | | | | | | | paintChild RenderInkWell at Point(400.0, 145.0) -2 | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | | paintChild RenderOpacity at Point(478.0, 159.0) +2 | | | | | | | | | paintChild RenderPositionedBox at Point(200.0, 0.0) +2 | | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | | | | paintChild RenderOpacity at Point(265.0, 14.0) +2 | | | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) +2 | | | | | | | | | | | translate(265.0, 14.0) +2 | | | | | | | | | | | translate(-265.0, -14.0) +2 | | | | | | | | | | | restore +2 | | | | | | | | paintChild RenderInkWell at Point(376.0, 0.0) 2 | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) -2 | | | | | | | | | translate(478.0, 159.0) -2 | | | | | | | | | translate(-478.0, -159.0) -2 | | | | | | | | | restore -2 | | | | | | | paintChild RenderInkWell at Point(592.0, 145.0) -2 | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | | paintChild RenderOpacity at Point(668.0, 159.0) +2 | | | | | | | | | paintChild RenderPositionedBox at Point(388.0, 0.0) +2 | | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | | | | paintChild RenderOpacity at Point(452.0, 14.0) +2 | | | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) +2 | | | | | | | | | | | translate(452.0, 14.0) +2 | | | | | | | | | | | translate(-452.0, -14.0) +2 | | | | | | | | | | | restore +2 | | | | | | | | paintChild RenderInkWell at Point(564.0, 0.0) 2 | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) -2 | | | | | | | | | translate(668.0, 159.0) -2 | | | | | | | | | translate(-668.0, -159.0) -2 | | | | | | | | | restore -2 | | | | | | paintChild RenderPositionedBox at Point(343.0, 193.0) -2 | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | paintChild RenderParagraph at Point(343.0, 354.5) +2 | | | | | | | | | paintChild RenderPositionedBox at Point(576.0, 0.0) +2 | | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | | | | paintChild RenderOpacity at Point(638.0, 14.0) +2 | | | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | | | | | saveLayer(null, Paint(color:Color(0xb3000000))) +2 | | | | | | | | | | | translate(638.0, 14.0) +2 | | | | | | | | | | | translate(-638.0, -14.0) +2 | | | | | | | | | | | restore +2 | | | | | | | | restore +2 | | | | | | | paintChild RenderPositionedBox at Point(343.0, 201.0) 2 | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 -2 | | | | | | | | translate(343.0, 354.5) -2 | | | | | | | | translate(-343.0, -354.5) +2 | | | | | | | | paintChild RenderParagraph at Point(343.0, 354.5) +2 | | | | | | | | | TestPaintingCanvas() constructor: 800.0 x 600.0 +2 | | | | | | | | | translate(343.0, 354.5) +2 | | | | | | | | | translate(-343.0, -354.5) 2 | | | | | | restore 2 | | paintChild RenderDecoratedBox at Point(0.0, 0.0) 2 | | | TestPaintingCanvas() constructor: 800.0 x 600.0