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 {
return new Table(
columnWidths: tableColumns.asMap(),
children: tableRows
children: tableRows,
);
}
}
......
......@@ -298,7 +298,7 @@ class RenderStack extends RenderBox
RenderStack({
List<RenderBox> children,
FractionalOffsetGeometry alignment: FractionalOffsetDirectional.topStart,
@required TextDirection textDirection,
TextDirection textDirection,
StackFit fit: StackFit.loose,
Overflow overflow: Overflow.clip,
}) : assert(alignment != null),
......@@ -569,7 +569,7 @@ class RenderIndexedStack extends RenderStack {
RenderIndexedStack({
List<RenderBox> children,
FractionalOffsetGeometry alignment: FractionalOffsetDirectional.topStart,
@required TextDirection textDirection,
TextDirection textDirection,
int index: 0,
}) : _index = index, super(
children: children,
......
......@@ -359,6 +359,7 @@ class RenderTable extends RenderBox {
int rows,
Map<int, TableColumnWidth> columnWidths,
TableColumnWidth defaultColumnWidth: const FlexColumnWidth(1.0),
@required TextDirection textDirection,
TableBorder border,
List<Decoration> rowDecorations,
ImageConfiguration configuration: ImageConfiguration.empty,
......@@ -370,7 +371,9 @@ class RenderTable extends RenderBox {
assert(rows == null || rows >= 0),
assert(rows == null || children == 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);
_rows = rows ?? 0;
_children = <RenderBox>[]..length = _columns * _rows;
......@@ -489,6 +492,17 @@ class RenderTable extends RenderBox {
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.
TableBorder get border => _border;
TableBorder _border;
......@@ -977,6 +991,8 @@ class RenderTable extends RenderBox {
@override
void performLayout() {
final int rows = this.rows;
final int columns = this.columns;
assert(_children.length == rows * columns);
if (rows * columns == 0) {
// TODO(ianh): if columns is zero, this should be zero width
......@@ -986,12 +1002,25 @@ class RenderTable extends RenderBox {
}
final List<double> widths = _computeColumnWidths(constraints);
final List<double> positions = new List<double>(columns);
_rowTops.clear();
positions[0] = 0.0;
for (int x = 1; x < columns; x += 1)
positions[x] = positions[x-1] + widths[x-1];
_columnLefts = positions;
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;
for (int x = 1; x < columns; x += 1)
positions[x] = positions[x-1] + widths[x-1];
_columnLefts = positions;
tableWidth = positions.last + widths.last;
break;
}
assert(!positions.any((double value) => value == null));
_rowTops.clear();
_baselineDistance = null;
// then, lay out each row
double rowTop = 0.0;
......@@ -1070,7 +1099,7 @@ class RenderTable extends RenderBox {
rowTop += rowHeight;
}
_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);
}
......@@ -1119,7 +1148,13 @@ class RenderTable extends RenderBox {
}
assert(_rows == _rowTops.length - 1);
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
......
......@@ -198,9 +198,9 @@ class TableBorder {
assert(rows.first == 0.0);
assert(rows.last == rect.height);
assert(columns != null);
assert(columns.length >= 2);
assert(columns.isNotEmpty);
assert(columns.first == 0.0);
assert(columns.last == rect.width);
assert(columns.last < rect.width);
final Paint paint = new Paint();
final Path path = new Path();
......
......@@ -7,6 +7,7 @@ import 'dart:collection';
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'basic.dart';
import 'debug.dart';
import 'framework.dart';
import 'image.dart';
......@@ -97,6 +98,7 @@ class Table extends RenderObjectWidget {
this.children: const <TableRow>[],
this.columnWidths,
this.defaultColumnWidth: const FlexColumnWidth(1.0),
this.textDirection,
this.border,
this.defaultVerticalAlignment: TableCellVerticalAlignment.top,
this.textBaseline
......@@ -179,6 +181,11 @@ class Table extends RenderObjectWidget {
/// `columnWidths[i]` is null.
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.
final TableBorder border;
......@@ -200,6 +207,7 @@ class Table extends RenderObjectWidget {
rows: children.length,
columnWidths: columnWidths,
defaultColumnWidth: defaultColumnWidth,
textDirection: textDirection ?? Directionality.of(context),
border: border,
rowDecorations: _rowDecorations,
configuration: createLocalImageConfiguration(context),
......@@ -215,6 +223,7 @@ class Table extends RenderObjectWidget {
renderObject
..columnWidths = columnWidths
..defaultColumnWidth = defaultColumnWidth
..textDirection = textDirection ?? Directionality.of(context)
..border = border
..rowDecorations = _rowDecorations
..configuration = createLocalImageConfiguration(context)
......
......@@ -16,7 +16,7 @@ RenderBox sizedBox(double width, double height) {
void main() {
test('Table control test; tight', () {
RenderTable table;
layout(table = new RenderTable());
layout(table = new RenderTable(textDirection: TextDirection.ltr));
expect(table.size.width, equals(800.0));
expect(table.size.height, equals(600.0));
......@@ -41,7 +41,7 @@ void main() {
test('Table control test; loose', () {
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)));
});
......@@ -52,8 +52,9 @@ void main() {
columns: 5,
rows: 5,
defaultColumnWidth: const IntrinsicColumnWidth(),
textDirection: TextDirection.ltr,
defaultVerticalAlignment: TableCellVerticalAlignment.baseline,
textBaseline: TextBaseline.alphabetic
textBaseline: TextBaseline.alphabetic,
)));
expect(table.size, equals(const Size(0.0, 0.0)));
......@@ -143,7 +144,8 @@ void main() {
RenderBox child;
table = new RenderTable(
columns: 5,
rows: 5
rows: 5,
textDirection: TextDirection.ltr,
);
table.setChild(4, 4, child = sizedBox(10.0, 10.0));
......@@ -159,7 +161,7 @@ void main() {
final RenderBox child1 = new RenderPositionedBox();
final RenderBox child2 = new RenderPositionedBox();
final RenderBox child3 = new RenderPositionedBox();
table = new RenderTable();
table = new RenderTable(textDirection: TextDirection.ltr);
table.setFlatChildren(3, <RenderBox>[child1, new RenderPositionedBox(), child2,
new RenderPositionedBox(), child3, new RenderPositionedBox()]);
expect(table.rows, equals(2));
......
......@@ -20,81 +20,267 @@ class TestStatefulWidgetState extends State<TestStatefulWidget> {
void main() {
testWidgets('Table widget - control test', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
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')
]
Future<Null> run(TextDirection textDirection) async {
await tester.pumpWidget(
new Directionality(
textDirection: textDirection,
child: new Table(
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'),
],
),
],
),
]
)
));
final RenderBox boxA = tester.renderObject(find.text('AAAAAA'));
final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G'));
final RenderBox boxB = tester.renderObject(find.text('B'));
expect(boxA.size, equals(boxD.size));
expect(boxA.size, equals(boxG.size));
expect(boxA.size, equals(boxB.size));
),
);
final RenderBox boxA = tester.renderObject(find.text('AAAAAA'));
final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G'));
final RenderBox boxB = tester.renderObject(find.text('B'));
expect(boxA.size, equals(boxD.size));
expect(boxA.size, equals(boxG.size));
expect(boxA.size, equals(boxB.size));
}
await run(TextDirection.ltr);
await tester.pumpWidget(new Container());
await run(TextDirection.rtl);
});
testWidgets('Table widget - changing table dimensions', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('A'), const Text('B'), const Text('C')
]
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'),
],
),
],
),
new TableRow(
children: <Widget>[
const Text('D'), const Text('E'), const Text('F')
]
),
),
);
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'),
],
),
],
),
new TableRow(
children: <Widget>[
const Text('G'), const Text('H'), const Text('I')
]
),
),
);
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 {
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('A'), const Text('B'), const Text('C'),
],
),
new TableRow(
children: <Widget>[
const Text('D'), const Text('E'), const Text('F'),
],
),
new TableRow(
children: <Widget>[
const Text('G'), const Text('H'), const Text('I'),
],
),
],
),
),
);
final RenderBox boxA1 = tester.renderObject(find.text('A'));
final RenderBox boxG1 = tester.renderObject(find.text('G'));
expect(boxA1, isNotNull);
expect(boxG1, isNotNull);
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('a'), const Text('b'), const Text('c'), const Text('d')
]
),
new TableRow(
children: <Widget>[
const Text('e'), const Text('f'), const Text('g'), const Text('h')
]
),
]
)
));
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('a'), const Text('b'), const Text('c'), const Text('d'),
],
),
new TableRow(
children: <Widget>[
const Text('e'), const Text('f'), const Text('g'), const Text('h'),
],
),
],
),
),
);
final RenderBox boxA2 = tester.renderObject(find.text('a'));
final RenderBox boxG2 = tester.renderObject(find.text('g'));
expect(boxA2, isNotNull);
......@@ -104,50 +290,54 @@ void main() {
});
testWidgets('Table widget - repump test', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
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 tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('AAA'), const Text('B'), const Text('C')
]
),
new TableRow(
children: <Widget>[
const Text('D'), const Text('E'), const Text('FFFFFF')
]
),
new TableRow(
children: <Widget>[
const Text('G'), const Text('H'), const Text('III')
]
),
]
)
));
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
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 tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('AAA'), const Text('B'), const Text('C'),
],
),
new TableRow(
children: <Widget>[
const Text('D'), const Text('E'), const Text('FFFFFF'),
],
),
new TableRow(
children: <Widget>[
const Text('G'), const Text('H'), const Text('III'),
],
),
],
),
),
);
final RenderBox boxA = tester.renderObject(find.text('AAA'));
final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G'));
......@@ -158,29 +348,31 @@ void main() {
});
testWidgets('Table widget - intrinsic sizing test', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality(
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('AAA'), const Text('B'), const Text('C')
]
),
new TableRow(
children: <Widget>[
const Text('D'), const Text('E'), const Text('FFFFFF')
]
),
new TableRow(
children: <Widget>[
const Text('G'), const Text('H'), const Text('III')
]
),
]
)
));
child: new Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('AAA'), const Text('B'), const Text('C'),
],
),
new TableRow(
children: <Widget>[
const Text('D'), const Text('E'), const Text('FFFFFF'),
],
),
new TableRow(
children: <Widget>[
const Text('G'), const Text('H'), const Text('III'),
],
),
],
),
),
);
final RenderBox boxA = tester.renderObject(find.text('AAA'));
final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G'));
......@@ -192,52 +384,56 @@ void main() {
});
testWidgets('Table widget - intrinsic sizing test, resizing', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
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 tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('A'), 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 tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
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 tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('A'), 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'),
],
),
],
),
),
);
final RenderBox boxA = tester.renderObject(find.text('A'));
final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G'));
......@@ -249,51 +445,55 @@ void main() {
});
testWidgets('Table widget - intrinsic sizing test, changing column widths', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('AAA'), const Text('B'), const Text('C')
]
),
new TableRow(
children: <Widget>[
const Text('D'), const Text('E'), const Text('FFFFFF')
]
),
new TableRow(
children: <Widget>[
const Text('G'), const Text('H'), const Text('III')
]
),
]
)
));
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('AAA'), const Text('B'), const Text('C')
]
),
new TableRow(
children: <Widget>[
const Text('D'), const Text('E'), const Text('FFFFFF')
]
),
new TableRow(
children: <Widget>[
const Text('G'), const Text('H'), const Text('III')
]
),
]
)
));
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('AAA'), const Text('B'), const Text('C'),
],
),
new TableRow(
children: <Widget>[
const Text('D'), const Text('E'), const Text('FFFFFF'),
],
),
new TableRow(
children: <Widget>[
const Text('G'), const Text('H'), const Text('III'),
],
),
],
),
),
);
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
defaultColumnWidth: const IntrinsicColumnWidth(),
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('AAA'), const Text('B'), const Text('C'),
],
),
new TableRow(
children: <Widget>[
const Text('D'), const Text('E'), const Text('FFFFFF'),
],
),
new TableRow(
children: <Widget>[
const Text('G'), const Text('H'), const Text('III'),
],
),
],
)
),
);
final RenderBox boxA = tester.renderObject(find.text('AAA'));
final RenderBox boxD = tester.renderObject(find.text('D'));
final RenderBox boxG = tester.renderObject(find.text('G'));
......@@ -306,78 +506,84 @@ void main() {
testWidgets('Table widget - moving test', (WidgetTester tester) async {
final List<BuildContext> contexts = <BuildContext>[];
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
key: const ValueKey<int>(1),
children: <Widget>[
new StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
contexts.add(context);
return const Text('A');
}
)
]
),
new TableRow(
children: <Widget>[
const Text('b')
]
),
]
)
));
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('b')
]
),
new TableRow(
key: const ValueKey<int>(1),
children: <Widget>[
new StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
contexts.add(context);
return const Text('A');
}
)
]
),
]
)
));
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
key: const ValueKey<int>(1),
children: <Widget>[
new StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
contexts.add(context);
return const Text('A');
},
),
],
),
new TableRow(
children: <Widget>[
const Text('b'),
],
),
],
),
),
);
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
const Text('b'),
],
),
new TableRow(
key: const ValueKey<int>(1),
children: <Widget>[
new StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
contexts.add(context);
return const Text('A');
},
),
],
),
],
),
),
);
expect(contexts.length, equals(2));
expect(contexts[0], equals(contexts[1]));
});
testWidgets('Table widget - keyed rows', (WidgetTester tester) async {
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
key: const ValueKey<int>(1),
children: <Widget>[
const TestStatefulWidget(key: const ValueKey<int>(11)),
const TestStatefulWidget(key: const ValueKey<int>(12)),
],
),
new TableRow(
key: const ValueKey<int>(2),
children: <Widget>[
const TestStatefulWidget(key: const ValueKey<int>(21)),
const TestStatefulWidget(key: const ValueKey<int>(22)),
],
),
]
)
));
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
key: const ValueKey<int>(1),
children: <Widget>[
const TestStatefulWidget(key: const ValueKey<int>(11)),
const TestStatefulWidget(key: const ValueKey<int>(12)),
],
),
new TableRow(
key: const ValueKey<int>(2),
children: <Widget>[
const TestStatefulWidget(key: const ValueKey<int>(21)),
const TestStatefulWidget(key: const ValueKey<int>(22)),
],
),
],
),
),
);
final TestStatefulWidgetState state11 = tester.state(find.byKey(const ValueKey<int>(11)));
final TestStatefulWidgetState state12 = tester.state(find.byKey(const ValueKey<int>(12)));
......@@ -389,20 +595,22 @@ void main() {
expect(state21.mounted, isTrue);
expect(state22.mounted, isTrue);
await tester.pumpWidget(new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
key: const ValueKey<int>(2),
children: <Widget>[
const TestStatefulWidget(key: const ValueKey<int>(21)),
const TestStatefulWidget(key: const ValueKey<int>(22)),
],
),
]
)
));
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: new Table(
children: <TableRow>[
new TableRow(
key: const ValueKey<int>(2),
children: <Widget>[
const TestStatefulWidget(key: const ValueKey<int>(21)),
const TestStatefulWidget(key: const ValueKey<int>(22)),
],
),
],
),
),
);
expect(state11.mounted, isFalse);
expect(state12.mounted, isFalse);
......@@ -415,23 +623,26 @@ void main() {
final Key tableKey = new UniqueKey();
await tester.pumpWidget(
new Column(
children: <Widget> [
new Expanded(
key: tableKey,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
new Container(key: const ValueKey<int>(1)),
new TestStatefulWidget(key: key),
new Container(key: const ValueKey<int>(2)),
],
),
],
new Directionality(
textDirection: TextDirection.ltr,
child: new Column(
children: <Widget> [
new Expanded(
key: tableKey,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
new Container(key: const ValueKey<int>(1)),
new TestStatefulWidget(key: key),
new Container(key: const ValueKey<int>(2)),
],
),
],
),
),
),
],
],
),
),
);
......@@ -439,23 +650,26 @@ void main() {
expect(table.row(0).length, 3);
await tester.pumpWidget(
new Column(
children: <Widget> [
new Expanded(child: new TestStatefulWidget(key: key)),
new Expanded(
key: tableKey,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
new Container(key: const ValueKey<int>(1)),
new Container(key: const ValueKey<int>(2)),
],
),
],
new Directionality(
textDirection: TextDirection.ltr,
child: new Column(
children: <Widget> [
new Expanded(child: new TestStatefulWidget(key: key)),
new Expanded(
key: tableKey,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
new Container(key: const ValueKey<int>(1)),
new Container(key: const ValueKey<int>(2)),
],
),
],
),
),
),
],
],
),
),
);
......@@ -463,23 +677,26 @@ void main() {
expect(table.row(0).length, 2);
await tester.pumpWidget(
new Column(
children: <Widget> [
new Expanded(
key: tableKey,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
new Container(key: const ValueKey<int>(1)),
new TestStatefulWidget(key: key),
new Container(key: const ValueKey<int>(2)),
],
),
],
new Directionality(
textDirection: TextDirection.ltr,
child: new Column(
children: <Widget> [
new Expanded(
key: tableKey,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
new Container(key: const ValueKey<int>(1)),
new TestStatefulWidget(key: key),
new Container(key: const ValueKey<int>(2)),
],
),
],
),
),
),
],
],
),
),
);
......@@ -487,23 +704,26 @@ void main() {
expect(table.row(0).length, 3);
await tester.pumpWidget(
new Column(
children: <Widget> [
new Expanded(
key: tableKey,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
new Container(key: const ValueKey<int>(1)),
new Container(key: const ValueKey<int>(2)),
],
),
],
new Directionality(
textDirection: TextDirection.ltr,
child: new Column(
children: <Widget> [
new Expanded(
key: tableKey,
child: new Table(
children: <TableRow>[
new TableRow(
children: <Widget>[
new Container(key: const ValueKey<int>(1)),
new Container(key: const ValueKey<int>(2)),
],
),
],
),
),
),
new Expanded(child: new TestStatefulWidget(key: key)),
],
new Expanded(child: new TestStatefulWidget(key: key)),
],
),
),
);
......
......@@ -473,4 +473,8 @@ class WidgetController {
assert(box != null);
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