Commit 1a0bdb96 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Add RTL support to Table (#12225)

Also, fix asserts in TableBorder#paint to match documentation.

Fixes #12009
parent fe27f864
...@@ -583,7 +583,7 @@ class DataTable extends StatelessWidget { ...@@ -583,7 +583,7 @@ class DataTable extends StatelessWidget {
return new Table( return new Table(
columnWidths: tableColumns.asMap(), columnWidths: tableColumns.asMap(),
children: tableRows children: tableRows,
); );
} }
} }
......
...@@ -298,7 +298,7 @@ class RenderStack extends RenderBox ...@@ -298,7 +298,7 @@ class RenderStack extends RenderBox
RenderStack({ RenderStack({
List<RenderBox> children, List<RenderBox> children,
FractionalOffsetGeometry alignment: FractionalOffsetDirectional.topStart, FractionalOffsetGeometry alignment: FractionalOffsetDirectional.topStart,
@required TextDirection textDirection, TextDirection textDirection,
StackFit fit: StackFit.loose, StackFit fit: StackFit.loose,
Overflow overflow: Overflow.clip, Overflow overflow: Overflow.clip,
}) : assert(alignment != null), }) : assert(alignment != null),
...@@ -569,7 +569,7 @@ class RenderIndexedStack extends RenderStack { ...@@ -569,7 +569,7 @@ class RenderIndexedStack extends RenderStack {
RenderIndexedStack({ RenderIndexedStack({
List<RenderBox> children, List<RenderBox> children,
FractionalOffsetGeometry alignment: FractionalOffsetDirectional.topStart, FractionalOffsetGeometry alignment: FractionalOffsetDirectional.topStart,
@required TextDirection textDirection, TextDirection textDirection,
int index: 0, int index: 0,
}) : _index = index, super( }) : _index = index, super(
children: children, children: children,
......
...@@ -359,6 +359,7 @@ class RenderTable extends RenderBox { ...@@ -359,6 +359,7 @@ class RenderTable extends RenderBox {
int rows, int rows,
Map<int, TableColumnWidth> columnWidths, Map<int, TableColumnWidth> columnWidths,
TableColumnWidth defaultColumnWidth: const FlexColumnWidth(1.0), TableColumnWidth defaultColumnWidth: const FlexColumnWidth(1.0),
@required TextDirection textDirection,
TableBorder border, TableBorder border,
List<Decoration> rowDecorations, List<Decoration> rowDecorations,
ImageConfiguration configuration: ImageConfiguration.empty, ImageConfiguration configuration: ImageConfiguration.empty,
...@@ -370,7 +371,9 @@ class RenderTable extends RenderBox { ...@@ -370,7 +371,9 @@ class RenderTable extends RenderBox {
assert(rows == null || rows >= 0), assert(rows == null || rows >= 0),
assert(rows == null || children == null), assert(rows == null || children == null),
assert(defaultColumnWidth != null), assert(defaultColumnWidth != null),
assert(configuration != null) { assert(textDirection != null),
assert(configuration != null),
_textDirection = textDirection {
_columns = columns ?? (children != null && children.isNotEmpty ? children.first.length : 0); _columns = columns ?? (children != null && children.isNotEmpty ? children.first.length : 0);
_rows = rows ?? 0; _rows = rows ?? 0;
_children = <RenderBox>[]..length = _columns * _rows; _children = <RenderBox>[]..length = _columns * _rows;
...@@ -489,6 +492,17 @@ class RenderTable extends RenderBox { ...@@ -489,6 +492,17 @@ class RenderTable extends RenderBox {
markNeedsLayout(); markNeedsLayout();
} }
/// The direction in which the columns are ordered.
TextDirection get textDirection => _textDirection;
TextDirection _textDirection;
set textDirection(TextDirection value) {
assert(value != null);
if (_textDirection == value)
return;
_textDirection = value;
markNeedsLayout();
}
/// The style to use when painting the boundary and interior divisions of the table. /// The style to use when painting the boundary and interior divisions of the table.
TableBorder get border => _border; TableBorder get border => _border;
TableBorder _border; TableBorder _border;
...@@ -977,6 +991,8 @@ class RenderTable extends RenderBox { ...@@ -977,6 +991,8 @@ class RenderTable extends RenderBox {
@override @override
void performLayout() { void performLayout() {
final int rows = this.rows;
final int columns = this.columns;
assert(_children.length == rows * columns); assert(_children.length == rows * columns);
if (rows * columns == 0) { if (rows * columns == 0) {
// TODO(ianh): if columns is zero, this should be zero width // TODO(ianh): if columns is zero, this should be zero width
...@@ -986,12 +1002,25 @@ class RenderTable extends RenderBox { ...@@ -986,12 +1002,25 @@ class RenderTable extends RenderBox {
} }
final List<double> widths = _computeColumnWidths(constraints); final List<double> widths = _computeColumnWidths(constraints);
final List<double> positions = new List<double>(columns); final List<double> positions = new List<double>(columns);
_rowTops.clear(); double tableWidth;
switch (textDirection) {
case TextDirection.rtl:
positions[columns - 1] = 0.0;
for (int x = columns - 2; x >= 0; x -= 1)
positions[x] = positions[x+1] + widths[x+1];
_columnLefts = positions.reversed.toList();
tableWidth = positions.first + widths.first;
break;
case TextDirection.ltr:
positions[0] = 0.0; positions[0] = 0.0;
for (int x = 1; x < columns; x += 1) for (int x = 1; x < columns; x += 1)
positions[x] = positions[x-1] + widths[x-1]; positions[x] = positions[x-1] + widths[x-1];
_columnLefts = positions; _columnLefts = positions;
tableWidth = positions.last + widths.last;
break;
}
assert(!positions.any((double value) => value == null)); assert(!positions.any((double value) => value == null));
_rowTops.clear();
_baselineDistance = null; _baselineDistance = null;
// then, lay out each row // then, lay out each row
double rowTop = 0.0; double rowTop = 0.0;
...@@ -1070,7 +1099,7 @@ class RenderTable extends RenderBox { ...@@ -1070,7 +1099,7 @@ class RenderTable extends RenderBox {
rowTop += rowHeight; rowTop += rowHeight;
} }
_rowTops.add(rowTop); _rowTops.add(rowTop);
size = constraints.constrain(new Size(positions.last + widths.last, rowTop)); size = constraints.constrain(new Size(tableWidth, rowTop));
assert(_rowTops.length == rows + 1); assert(_rowTops.length == rows + 1);
} }
...@@ -1119,7 +1148,13 @@ class RenderTable extends RenderBox { ...@@ -1119,7 +1148,13 @@ class RenderTable extends RenderBox {
} }
assert(_rows == _rowTops.length - 1); assert(_rows == _rowTops.length - 1);
assert(_columns == _columnLefts.length); assert(_columns == _columnLefts.length);
border?.paint(context.canvas, offset & size, rows: _rowTops, columns: _columnLefts); if (border != null) {
// The border rect might not fill the entire height of this render object
// if the rows underflow. We always force the columns to fill the width of
// the render object, which means the columns cannot underflow.
final Rect borderRect = new Rect.fromLTWH(offset.dx, offset.dy, size.width, _rowTops.last);
border?.paint(context.canvas, borderRect, rows: _rowTops, columns: _columnLefts);
}
} }
@override @override
......
...@@ -198,9 +198,9 @@ class TableBorder { ...@@ -198,9 +198,9 @@ class TableBorder {
assert(rows.first == 0.0); assert(rows.first == 0.0);
assert(rows.last == rect.height); assert(rows.last == rect.height);
assert(columns != null); assert(columns != null);
assert(columns.length >= 2); assert(columns.isNotEmpty);
assert(columns.first == 0.0); assert(columns.first == 0.0);
assert(columns.last == rect.width); assert(columns.last < rect.width);
final Paint paint = new Paint(); final Paint paint = new Paint();
final Path path = new Path(); final Path path = new Path();
......
...@@ -7,6 +7,7 @@ import 'dart:collection'; ...@@ -7,6 +7,7 @@ import 'dart:collection';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'basic.dart';
import 'debug.dart'; import 'debug.dart';
import 'framework.dart'; import 'framework.dart';
import 'image.dart'; import 'image.dart';
...@@ -97,6 +98,7 @@ class Table extends RenderObjectWidget { ...@@ -97,6 +98,7 @@ class Table extends RenderObjectWidget {
this.children: const <TableRow>[], this.children: const <TableRow>[],
this.columnWidths, this.columnWidths,
this.defaultColumnWidth: const FlexColumnWidth(1.0), this.defaultColumnWidth: const FlexColumnWidth(1.0),
this.textDirection,
this.border, this.border,
this.defaultVerticalAlignment: TableCellVerticalAlignment.top, this.defaultVerticalAlignment: TableCellVerticalAlignment.top,
this.textBaseline this.textBaseline
...@@ -179,6 +181,11 @@ class Table extends RenderObjectWidget { ...@@ -179,6 +181,11 @@ class Table extends RenderObjectWidget {
/// `columnWidths[i]` is null. /// `columnWidths[i]` is null.
final TableColumnWidth defaultColumnWidth; final TableColumnWidth defaultColumnWidth;
/// The direction in which the columns are ordered.
///
/// Defaults to the ambient [Directionality].
final TextDirection textDirection;
/// The style to use when painting the boundary and interior divisions of the table. /// The style to use when painting the boundary and interior divisions of the table.
final TableBorder border; final TableBorder border;
...@@ -200,6 +207,7 @@ class Table extends RenderObjectWidget { ...@@ -200,6 +207,7 @@ class Table extends RenderObjectWidget {
rows: children.length, rows: children.length,
columnWidths: columnWidths, columnWidths: columnWidths,
defaultColumnWidth: defaultColumnWidth, defaultColumnWidth: defaultColumnWidth,
textDirection: textDirection ?? Directionality.of(context),
border: border, border: border,
rowDecorations: _rowDecorations, rowDecorations: _rowDecorations,
configuration: createLocalImageConfiguration(context), configuration: createLocalImageConfiguration(context),
...@@ -215,6 +223,7 @@ class Table extends RenderObjectWidget { ...@@ -215,6 +223,7 @@ class Table extends RenderObjectWidget {
renderObject renderObject
..columnWidths = columnWidths ..columnWidths = columnWidths
..defaultColumnWidth = defaultColumnWidth ..defaultColumnWidth = defaultColumnWidth
..textDirection = textDirection ?? Directionality.of(context)
..border = border ..border = border
..rowDecorations = _rowDecorations ..rowDecorations = _rowDecorations
..configuration = createLocalImageConfiguration(context) ..configuration = createLocalImageConfiguration(context)
......
...@@ -16,7 +16,7 @@ RenderBox sizedBox(double width, double height) { ...@@ -16,7 +16,7 @@ RenderBox sizedBox(double width, double height) {
void main() { void main() {
test('Table control test; tight', () { test('Table control test; tight', () {
RenderTable table; RenderTable table;
layout(table = new RenderTable()); layout(table = new RenderTable(textDirection: TextDirection.ltr));
expect(table.size.width, equals(800.0)); expect(table.size.width, equals(800.0));
expect(table.size.height, equals(600.0)); expect(table.size.height, equals(600.0));
...@@ -41,7 +41,7 @@ void main() { ...@@ -41,7 +41,7 @@ void main() {
test('Table control test; loose', () { test('Table control test; loose', () {
RenderTable table; RenderTable table;
layout(new RenderPositionedBox(child: table = new RenderTable())); layout(new RenderPositionedBox(child: table = new RenderTable(textDirection: TextDirection.ltr)));
expect(table.size, equals(const Size(0.0, 0.0))); expect(table.size, equals(const Size(0.0, 0.0)));
}); });
...@@ -52,8 +52,9 @@ void main() { ...@@ -52,8 +52,9 @@ void main() {
columns: 5, columns: 5,
rows: 5, rows: 5,
defaultColumnWidth: const IntrinsicColumnWidth(), defaultColumnWidth: const IntrinsicColumnWidth(),
textDirection: TextDirection.ltr,
defaultVerticalAlignment: TableCellVerticalAlignment.baseline, defaultVerticalAlignment: TableCellVerticalAlignment.baseline,
textBaseline: TextBaseline.alphabetic textBaseline: TextBaseline.alphabetic,
))); )));
expect(table.size, equals(const Size(0.0, 0.0))); expect(table.size, equals(const Size(0.0, 0.0)));
...@@ -143,7 +144,8 @@ void main() { ...@@ -143,7 +144,8 @@ void main() {
RenderBox child; RenderBox child;
table = new RenderTable( table = new RenderTable(
columns: 5, columns: 5,
rows: 5 rows: 5,
textDirection: TextDirection.ltr,
); );
table.setChild(4, 4, child = sizedBox(10.0, 10.0)); table.setChild(4, 4, child = sizedBox(10.0, 10.0));
...@@ -159,7 +161,7 @@ void main() { ...@@ -159,7 +161,7 @@ void main() {
final RenderBox child1 = new RenderPositionedBox(); final RenderBox child1 = new RenderPositionedBox();
final RenderBox child2 = new RenderPositionedBox(); final RenderBox child2 = new RenderPositionedBox();
final RenderBox child3 = new RenderPositionedBox(); final RenderBox child3 = new RenderPositionedBox();
table = new RenderTable(); table = new RenderTable(textDirection: TextDirection.ltr);
table.setFlatChildren(3, <RenderBox>[child1, new RenderPositionedBox(), child2, table.setFlatChildren(3, <RenderBox>[child1, new RenderPositionedBox(), child2,
new RenderPositionedBox(), child3, new RenderPositionedBox()]); new RenderPositionedBox(), child3, new RenderPositionedBox()]);
expect(table.rows, equals(2)); expect(table.rows, equals(2));
......
...@@ -20,28 +20,31 @@ class TestStatefulWidgetState extends State<TestStatefulWidget> { ...@@ -20,28 +20,31 @@ class TestStatefulWidgetState extends State<TestStatefulWidget> {
void main() { void main() {
testWidgets('Table widget - control test', (WidgetTester tester) async { testWidgets('Table widget - control test', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality( Future<Null> run(TextDirection textDirection) async {
textDirection: TextDirection.ltr, await tester.pumpWidget(
new Directionality(
textDirection: textDirection,
child: new Table( child: new Table(
children: <TableRow>[ children: <TableRow>[
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('AAAAAA'), const Text('B'), const Text('C') const Text('AAAAAA'), const Text('B'), const Text('C'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('D'), const Text('EEE'), const Text('F') const Text('D'), const Text('EEE'), const Text('F'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('G'), const Text('H'), const Text('III') const Text('G'), const Text('H'), const Text('III'),
] ],
), ),
] ],
) ),
)); ),
);
final RenderBox boxA = tester.renderObject(find.text('AAAAAA')); final RenderBox boxA = tester.renderObject(find.text('AAAAAA'));
final RenderBox boxD = tester.renderObject(find.text('D')); final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G')); final RenderBox boxG = tester.renderObject(find.text('G'));
...@@ -49,52 +52,235 @@ void main() { ...@@ -49,52 +52,235 @@ void main() {
expect(boxA.size, equals(boxD.size)); expect(boxA.size, equals(boxD.size));
expect(boxA.size, equals(boxG.size)); expect(boxA.size, equals(boxG.size));
expect(boxA.size, equals(boxB.size)); expect(boxA.size, equals(boxB.size));
}
await run(TextDirection.ltr);
await tester.pumpWidget(new Container());
await run(TextDirection.rtl);
});
testWidgets('Table widget - column offset (LTR)', (WidgetTester tester) async {
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Center(
child: new Table(
columnWidths: const <int, TableColumnWidth> {
0: const FixedColumnWidth(100.0),
1: const FixedColumnWidth(110.0),
2: const FixedColumnWidth(125.0),
},
defaultColumnWidth: const FixedColumnWidth(333.0),
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('A1'), const Text('B1'), const Text('C1'),
],
),
new TableRow(
children: <Widget>[
const Text('A2'), const Text('B2'), const Text('C2'),
],
),
new TableRow(
children: <Widget>[
const Text('A3'), const Text('B3'), const Text('C3'),
],
),
],
),
),
),
);
final Rect table = tester.getRect(find.byType(Table));
final Rect a1 = tester.getRect(find.text('A1'));
final Rect a2 = tester.getRect(find.text('A2'));
final Rect a3 = tester.getRect(find.text('A3'));
final Rect b1 = tester.getRect(find.text('B1'));
final Rect b2 = tester.getRect(find.text('B2'));
final Rect b3 = tester.getRect(find.text('B3'));
final Rect c1 = tester.getRect(find.text('C1'));
final Rect c2 = tester.getRect(find.text('C2'));
final Rect c3 = tester.getRect(find.text('C3'));
expect(a1.width, equals(100.0));
expect(a2.width, equals(100.0));
expect(a3.width, equals(100.0));
expect(b1.width, equals(110.0));
expect(b2.width, equals(110.0));
expect(b3.width, equals(110.0));
expect(c1.width, equals(125.0));
expect(c2.width, equals(125.0));
expect(c3.width, equals(125.0));
expect(table.width, equals(335.0));
expect(a1.left, equals(table.left));
expect(a2.left, equals(a1.left));
expect(a3.left, equals(a1.left));
expect(b1.left, equals(table.left + a1.width));
expect(b2.left, equals(b1.left));
expect(b3.left, equals(b1.left));
expect(c1.left, equals(table.left + a1.width + b1.width));
expect(c2.left, equals(c1.left));
expect(c3.left, equals(c1.left));
});
testWidgets('Table widget - column offset (RTL)', (WidgetTester tester) async {
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.rtl,
child: new Center(
child: new Table(
columnWidths: const <int, TableColumnWidth> {
0: const FixedColumnWidth(100.0),
1: const FixedColumnWidth(110.0),
2: const FixedColumnWidth(125.0),
},
defaultColumnWidth: const FixedColumnWidth(333.0),
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('A1'), const Text('B1'), const Text('C1'),
],
),
new TableRow(
children: <Widget>[
const Text('A2'), const Text('B2'), const Text('C2'),
],
),
new TableRow(
children: <Widget>[
const Text('A3'), const Text('B3'), const Text('C3'),
],
),
],
),
),
),
);
final Rect table = tester.getRect(find.byType(Table));
final Rect a1 = tester.getRect(find.text('A1'));
final Rect a2 = tester.getRect(find.text('A2'));
final Rect a3 = tester.getRect(find.text('A3'));
final Rect b1 = tester.getRect(find.text('B1'));
final Rect b2 = tester.getRect(find.text('B2'));
final Rect b3 = tester.getRect(find.text('B3'));
final Rect c1 = tester.getRect(find.text('C1'));
final Rect c2 = tester.getRect(find.text('C2'));
final Rect c3 = tester.getRect(find.text('C3'));
expect(a1.width, equals(100.0));
expect(a2.width, equals(100.0));
expect(a3.width, equals(100.0));
expect(b1.width, equals(110.0));
expect(b2.width, equals(110.0));
expect(b3.width, equals(110.0));
expect(c1.width, equals(125.0));
expect(c2.width, equals(125.0));
expect(c3.width, equals(125.0));
expect(table.width, equals(335.0));
expect(a1.right, equals(table.right));
expect(a2.right, equals(a1.right));
expect(a3.right, equals(a1.right));
expect(b1.right, equals(table.right - a1.width));
expect(b2.right, equals(b1.right));
expect(b3.right, equals(b1.right));
expect(c1.right, equals(table.right - a1.width - b1.width));
expect(c2.right, equals(c1.right));
expect(c3.right, equals(c1.right));
});
testWidgets('Table border - smoke test', (WidgetTester tester) async {
Future<Null> run(TextDirection textDirection) async {
await tester.pumpWidget(
new Directionality(
textDirection: textDirection,
child: new Table(
border: new TableBorder.all(),
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('AAAAAA'), const Text('B'), const Text('C'),
],
),
new TableRow(
children: <Widget>[
const Text('D'), const Text('EEE'), const Text('F'),
],
),
new TableRow(
children: <Widget>[
const Text('G'), const Text('H'), const Text('III'),
],
),
],
),
),
);
}
await run(TextDirection.ltr);
await tester.pumpWidget(new Container());
await run(TextDirection.rtl);
}); });
testWidgets('Table widget - changing table dimensions', (WidgetTester tester) async { testWidgets('Table widget - changing table dimensions', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality( await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
children: <TableRow>[ children: <TableRow>[
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('A'), const Text('B'), const Text('C') const Text('A'), const Text('B'), const Text('C'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('D'), const Text('E'), const Text('F') const Text('D'), const Text('E'), const Text('F'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('G'), const Text('H'), const Text('I') const Text('G'), const Text('H'), const Text('I'),
] ],
), ),
] ],
) ),
)); ),
);
final RenderBox boxA1 = tester.renderObject(find.text('A')); final RenderBox boxA1 = tester.renderObject(find.text('A'));
final RenderBox boxG1 = tester.renderObject(find.text('G')); final RenderBox boxG1 = tester.renderObject(find.text('G'));
expect(boxA1, isNotNull); expect(boxA1, isNotNull);
expect(boxG1, isNotNull); expect(boxG1, isNotNull);
await tester.pumpWidget(new Directionality( await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
children: <TableRow>[ children: <TableRow>[
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('a'), const Text('b'), const Text('c'), const Text('d') const Text('a'), const Text('b'), const Text('c'), const Text('d'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('e'), const Text('f'), const Text('g'), const Text('h') const Text('e'), const Text('f'), const Text('g'), const Text('h'),
] ],
), ),
] ],
) ),
)); ),
);
final RenderBox boxA2 = tester.renderObject(find.text('a')); final RenderBox boxA2 = tester.renderObject(find.text('a'));
final RenderBox boxG2 = tester.renderObject(find.text('g')); final RenderBox boxG2 = tester.renderObject(find.text('g'));
expect(boxA2, isNotNull); expect(boxA2, isNotNull);
...@@ -104,50 +290,54 @@ void main() { ...@@ -104,50 +290,54 @@ void main() {
}); });
testWidgets('Table widget - repump test', (WidgetTester tester) async { testWidgets('Table widget - repump test', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality( await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
children: <TableRow>[ children: <TableRow>[
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('AAAAAA'), const Text('B'), const Text('C') const Text('AAAAAA'), const Text('B'), const Text('C'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('D'), const Text('EEE'), const Text('F') const Text('D'), const Text('EEE'), const Text('F'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('G'), const Text('H'), const Text('III') const Text('G'), const Text('H'), const Text('III'),
] ],
), ),
] ],
) ),
)); ),
await tester.pumpWidget(new Directionality( );
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
children: <TableRow>[ children: <TableRow>[
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('AAA'), const Text('B'), const Text('C') const Text('AAA'), const Text('B'), const Text('C'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('D'), const Text('E'), const Text('FFFFFF') const Text('D'), const Text('E'), const Text('FFFFFF'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('G'), const Text('H'), const Text('III') const Text('G'), const Text('H'), const Text('III'),
] ],
), ),
] ],
) ),
)); ),
);
final RenderBox boxA = tester.renderObject(find.text('AAA')); final RenderBox boxA = tester.renderObject(find.text('AAA'));
final RenderBox boxD = tester.renderObject(find.text('D')); final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G')); final RenderBox boxG = tester.renderObject(find.text('G'));
...@@ -158,29 +348,31 @@ void main() { ...@@ -158,29 +348,31 @@ void main() {
}); });
testWidgets('Table widget - intrinsic sizing test', (WidgetTester tester) async { testWidgets('Table widget - intrinsic sizing test', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality( await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
defaultColumnWidth: const IntrinsicColumnWidth(), defaultColumnWidth: const IntrinsicColumnWidth(),
children: <TableRow>[ children: <TableRow>[
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('AAA'), const Text('B'), const Text('C') const Text('AAA'), const Text('B'), const Text('C'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('D'), const Text('E'), const Text('FFFFFF') const Text('D'), const Text('E'), const Text('FFFFFF'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('G'), const Text('H'), const Text('III') const Text('G'), const Text('H'), const Text('III'),
] ],
), ),
] ],
) ),
)); ),
);
final RenderBox boxA = tester.renderObject(find.text('AAA')); final RenderBox boxA = tester.renderObject(find.text('AAA'));
final RenderBox boxD = tester.renderObject(find.text('D')); final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G')); final RenderBox boxG = tester.renderObject(find.text('G'));
...@@ -192,52 +384,56 @@ void main() { ...@@ -192,52 +384,56 @@ void main() {
}); });
testWidgets('Table widget - intrinsic sizing test, resizing', (WidgetTester tester) async { testWidgets('Table widget - intrinsic sizing test, resizing', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality( await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
defaultColumnWidth: const IntrinsicColumnWidth(), defaultColumnWidth: const IntrinsicColumnWidth(),
children: <TableRow>[ children: <TableRow>[
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('AAAAAA'), const Text('B'), const Text('C') const Text('AAAAAA'), const Text('B'), const Text('C'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('D'), const Text('EEE'), const Text('F') const Text('D'), const Text('EEE'), const Text('F'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('G'), const Text('H'), const Text('III') const Text('G'), const Text('H'), const Text('III'),
] ],
), ),
] ],
) ),
)); ),
await tester.pumpWidget(new Directionality( );
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
defaultColumnWidth: const IntrinsicColumnWidth(), defaultColumnWidth: const IntrinsicColumnWidth(),
children: <TableRow>[ children: <TableRow>[
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('A'), const Text('B'), const Text('C') const Text('A'), const Text('B'), const Text('C'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('D'), const Text('EEE'), const Text('F') const Text('D'), const Text('EEE'), const Text('F'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('G'), const Text('H'), const Text('III') const Text('G'), const Text('H'), const Text('III'),
] ],
), ),
] ],
) ),
)); ),
);
final RenderBox boxA = tester.renderObject(find.text('A')); final RenderBox boxA = tester.renderObject(find.text('A'));
final RenderBox boxD = tester.renderObject(find.text('D')); final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G')); final RenderBox boxG = tester.renderObject(find.text('G'));
...@@ -249,51 +445,55 @@ void main() { ...@@ -249,51 +445,55 @@ void main() {
}); });
testWidgets('Table widget - intrinsic sizing test, changing column widths', (WidgetTester tester) async { testWidgets('Table widget - intrinsic sizing test, changing column widths', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality( await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
children: <TableRow>[ children: <TableRow>[
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('AAA'), const Text('B'), const Text('C') const Text('AAA'), const Text('B'), const Text('C'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('D'), const Text('E'), const Text('FFFFFF') const Text('D'), const Text('E'), const Text('FFFFFF'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('G'), const Text('H'), const Text('III') const Text('G'), const Text('H'), const Text('III'),
] ],
), ),
] ],
) ),
)); ),
await tester.pumpWidget(new Directionality( );
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
defaultColumnWidth: const IntrinsicColumnWidth(), defaultColumnWidth: const IntrinsicColumnWidth(),
children: <TableRow>[ children: <TableRow>[
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('AAA'), const Text('B'), const Text('C') const Text('AAA'), const Text('B'), const Text('C'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('D'), const Text('E'), const Text('FFFFFF') const Text('D'), const Text('E'), const Text('FFFFFF'),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('G'), const Text('H'), const Text('III') const Text('G'), const Text('H'), const Text('III'),
] ],
), ),
] ],
) )
)); ),
);
final RenderBox boxA = tester.renderObject(find.text('AAA')); final RenderBox boxA = tester.renderObject(find.text('AAA'));
final RenderBox boxD = tester.renderObject(find.text('D')); final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G')); final RenderBox boxG = tester.renderObject(find.text('G'));
...@@ -306,7 +506,8 @@ void main() { ...@@ -306,7 +506,8 @@ void main() {
testWidgets('Table widget - moving test', (WidgetTester tester) async { testWidgets('Table widget - moving test', (WidgetTester tester) async {
final List<BuildContext> contexts = <BuildContext>[]; final List<BuildContext> contexts = <BuildContext>[];
await tester.pumpWidget(new Directionality( await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
children: <TableRow>[ children: <TableRow>[
...@@ -317,26 +518,28 @@ void main() { ...@@ -317,26 +518,28 @@ void main() {
builder: (BuildContext context, StateSetter setState) { builder: (BuildContext context, StateSetter setState) {
contexts.add(context); contexts.add(context);
return const Text('A'); return const Text('A');
} },
) ),
] ],
), ),
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('b') const Text('b'),
] ],
), ),
] ],
) ),
)); ),
await tester.pumpWidget(new Directionality( );
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
children: <TableRow>[ children: <TableRow>[
new TableRow( new TableRow(
children: <Widget>[ children: <Widget>[
const Text('b') const Text('b'),
] ],
), ),
new TableRow( new TableRow(
key: const ValueKey<int>(1), key: const ValueKey<int>(1),
...@@ -345,19 +548,21 @@ void main() { ...@@ -345,19 +548,21 @@ void main() {
builder: (BuildContext context, StateSetter setState) { builder: (BuildContext context, StateSetter setState) {
contexts.add(context); contexts.add(context);
return const Text('A'); return const Text('A');
} },
)
]
), ),
] ],
) ),
)); ],
),
),
);
expect(contexts.length, equals(2)); expect(contexts.length, equals(2));
expect(contexts[0], equals(contexts[1])); expect(contexts[0], equals(contexts[1]));
}); });
testWidgets('Table widget - keyed rows', (WidgetTester tester) async { testWidgets('Table widget - keyed rows', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality( await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
children: <TableRow>[ children: <TableRow>[
...@@ -375,9 +580,10 @@ void main() { ...@@ -375,9 +580,10 @@ void main() {
const TestStatefulWidget(key: const ValueKey<int>(22)), const TestStatefulWidget(key: const ValueKey<int>(22)),
], ],
), ),
] ],
) ),
)); ),
);
final TestStatefulWidgetState state11 = tester.state(find.byKey(const ValueKey<int>(11))); final TestStatefulWidgetState state11 = tester.state(find.byKey(const ValueKey<int>(11)));
final TestStatefulWidgetState state12 = tester.state(find.byKey(const ValueKey<int>(12))); final TestStatefulWidgetState state12 = tester.state(find.byKey(const ValueKey<int>(12)));
...@@ -389,7 +595,8 @@ void main() { ...@@ -389,7 +595,8 @@ void main() {
expect(state21.mounted, isTrue); expect(state21.mounted, isTrue);
expect(state22.mounted, isTrue); expect(state22.mounted, isTrue);
await tester.pumpWidget(new Directionality( await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: new Table( child: new Table(
children: <TableRow>[ children: <TableRow>[
...@@ -400,9 +607,10 @@ void main() { ...@@ -400,9 +607,10 @@ void main() {
const TestStatefulWidget(key: const ValueKey<int>(22)), const TestStatefulWidget(key: const ValueKey<int>(22)),
], ],
), ),
] ],
) ),
)); ),
);
expect(state11.mounted, isFalse); expect(state11.mounted, isFalse);
expect(state12.mounted, isFalse); expect(state12.mounted, isFalse);
...@@ -415,7 +623,9 @@ void main() { ...@@ -415,7 +623,9 @@ void main() {
final Key tableKey = new UniqueKey(); final Key tableKey = new UniqueKey();
await tester.pumpWidget( await tester.pumpWidget(
new Column( new Directionality(
textDirection: TextDirection.ltr,
child: new Column(
children: <Widget> [ children: <Widget> [
new Expanded( new Expanded(
key: tableKey, key: tableKey,
...@@ -433,13 +643,16 @@ void main() { ...@@ -433,13 +643,16 @@ void main() {
), ),
], ],
), ),
),
); );
final RenderTable table = tester.renderObject(find.byType(Table)); final RenderTable table = tester.renderObject(find.byType(Table));
expect(table.row(0).length, 3); expect(table.row(0).length, 3);
await tester.pumpWidget( await tester.pumpWidget(
new Column( new Directionality(
textDirection: TextDirection.ltr,
child: new Column(
children: <Widget> [ children: <Widget> [
new Expanded(child: new TestStatefulWidget(key: key)), new Expanded(child: new TestStatefulWidget(key: key)),
new Expanded( new Expanded(
...@@ -457,13 +670,16 @@ void main() { ...@@ -457,13 +670,16 @@ void main() {
), ),
], ],
), ),
),
); );
expect(tester.renderObject(find.byType(Table)), equals(table)); expect(tester.renderObject(find.byType(Table)), equals(table));
expect(table.row(0).length, 2); expect(table.row(0).length, 2);
await tester.pumpWidget( await tester.pumpWidget(
new Column( new Directionality(
textDirection: TextDirection.ltr,
child: new Column(
children: <Widget> [ children: <Widget> [
new Expanded( new Expanded(
key: tableKey, key: tableKey,
...@@ -481,13 +697,16 @@ void main() { ...@@ -481,13 +697,16 @@ void main() {
), ),
], ],
), ),
),
); );
expect(tester.renderObject(find.byType(Table)), equals(table)); expect(tester.renderObject(find.byType(Table)), equals(table));
expect(table.row(0).length, 3); expect(table.row(0).length, 3);
await tester.pumpWidget( await tester.pumpWidget(
new Column( new Directionality(
textDirection: TextDirection.ltr,
child: new Column(
children: <Widget> [ children: <Widget> [
new Expanded( new Expanded(
key: tableKey, key: tableKey,
...@@ -505,6 +724,7 @@ void main() { ...@@ -505,6 +724,7 @@ void main() {
new Expanded(child: new TestStatefulWidget(key: key)), new Expanded(child: new TestStatefulWidget(key: key)),
], ],
), ),
),
); );
expect(tester.renderObject(find.byType(Table)), equals(table)); expect(tester.renderObject(find.byType(Table)), equals(table));
......
...@@ -473,4 +473,8 @@ class WidgetController { ...@@ -473,4 +473,8 @@ class WidgetController {
assert(box != null); assert(box != null);
return box.size; return box.size;
} }
/// Returns the rect of the given widget. This is only valid once
/// the widget's render object has been laid out at least once.
Rect getRect(Finder finder) => getTopLeft(finder) & getSize(finder);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment