Commit 6ea7ab89 authored by Ian Hickson's avatar Ian Hickson

Add a row decoration to RenderTable

This will let us draw in-row bottom borders and row-wide backgrounds,

both of which are necessary for Material data tables.
parent d748186c
......@@ -345,6 +345,8 @@ class RenderTable extends RenderBox {
Map<int, TableColumnWidth> columnWidths,
TableColumnWidth defaultColumnWidth: const FlexColumnWidth(1.0),
TableBorder border,
List<Decoration> rowDecorations,
Decoration defaultRowDecoration,
TableCellVerticalAlignment defaultVerticalAlignment: TableCellVerticalAlignment.top,
TextBaseline textBaseline,
List<List<RenderBox>> children
......@@ -359,6 +361,7 @@ class RenderTable extends RenderBox {
_columnWidths = columnWidths ?? new HashMap<int, TableColumnWidth>();
_defaultColumnWidth = defaultColumnWidth;
_border = border;
this.rowDecorations = rowDecorations; // must use setter to initialize box painters
_defaultVerticalAlignment = defaultVerticalAlignment;
_textBaseline = textBaseline;
if (children != null) {
......@@ -367,8 +370,6 @@ class RenderTable extends RenderBox {
}
}
// TODO(ianh): Add a 'decoration' field to the children's parent data, to paint on each cell.
// Children are stored in row-major order.
// _children.length must be rows * columns
List<RenderBox> _children = const <RenderBox>[];
......@@ -419,8 +420,8 @@ class RenderTable extends RenderBox {
markNeedsLayout();
}
Map<int, TableColumnWidth> _columnWidths;
Map<int, TableColumnWidth> get columnWidths => new Map<int, TableColumnWidth>.unmodifiable(_columnWidths);
Map<int, TableColumnWidth> _columnWidths;
void set columnWidths(Map<int, TableColumnWidth> value) {
value ??= new HashMap<int, TableColumnWidth>();
if (_columnWidths == value)
......@@ -454,6 +455,38 @@ class RenderTable extends RenderBox {
_border = value;
markNeedsPaint();
}
List<Decoration> get rowDecorations => new List<Decoration>.unmodifiable(_rowDecorations ?? const <Decoration>[]);
List<Decoration> _rowDecorations;
List<BoxPainter> _rowDecorationPainters;
void set rowDecorations(List<Decoration> value) {
if (_rowDecorations == value)
return;
_removeListenersIfNeeded();
_rowDecorations = value;
_rowDecorationPainters = _rowDecorations != null ? new List<BoxPainter>(_rowDecorations.length) : null;
_addListenersIfNeeded();
}
void _removeListenersIfNeeded() {
Set<Decoration> visitedDecorations = new Set<Decoration>();
if (_rowDecorations != null && attached) {
for (Decoration decoration in _rowDecorations) {
if (decoration != null && decoration.needsListeners && visitedDecorations.add(decoration))
decoration.removeChangeListener(markNeedsPaint);
}
}
}
void _addListenersIfNeeded() {
Set<Decoration> visitedDecorations = new Set<Decoration>();
if (_rowDecorations != null && attached) {
for (Decoration decoration in _rowDecorations) {
if (decoration != null && decoration.needsListeners && visitedDecorations.add(decoration))
decoration.addChangeListener(markNeedsPaint);
}
}
}
TableCellVerticalAlignment get defaultVerticalAlignment => _defaultVerticalAlignment;
TableCellVerticalAlignment _defaultVerticalAlignment;
......@@ -581,13 +614,15 @@ class RenderTable extends RenderBox {
super.attach(owner);
for (RenderBox child in _children)
child?.attach(owner);
_addListenersIfNeeded();
}
@override
void detach() {
super.detach();
_removeListenersIfNeeded();
for (RenderBox child in _children)
child?.detach();
super.detach();
}
@override
......@@ -823,8 +858,9 @@ class RenderTable extends RenderBox {
}
rowTop += rowHeight;
}
_rowTops.add(rowTop);
size = constraints.constrain(new Size(positions.last + widths.last, rowTop));
assert(_rowTops.length == rows);
assert(_rowTops.length == rows + 1);
}
@override
......@@ -845,10 +881,25 @@ class RenderTable extends RenderBox {
@override
void paint(PaintingContext context, Offset offset) {
Canvas canvas;
assert(_children.length == rows * columns);
if (rows * columns == 0)
return;
assert(_rowTops.length == rows);
assert(_rowTops.length == rows + 1);
canvas = context.canvas;
if (_rowDecorations != null) {
for (int y = 0; y < rows; y += 1) {
if (_rowDecorations.length <= y)
break;
_rowDecorationPainters[y] ??= _rowDecorations[y].createBoxPainter();
_rowDecorationPainters[y].paint(canvas, new Rect.fromLTRB(
offset.dx,
offset.dy + _rowTops[y],
offset.dx + size.width,
offset.dy + _rowTops[y+1]
));
}
}
for (int index = 0; index < _children.length; index += 1) {
RenderBox child = _children[index];
if (child != null) {
......@@ -856,9 +907,8 @@ class RenderTable extends RenderBox {
context.paintChild(child, childParentData.offset + offset);
}
}
canvas = context.canvas;
Rect bounds = offset & size;
Canvas canvas = context.canvas;
canvas.saveLayer(bounds, new Paint());
if (border != null) {
switch (border.verticalInside.style) {
case BorderStyle.solid:
......@@ -892,7 +942,6 @@ class RenderTable extends RenderBox {
}
border.paint(canvas, bounds);
}
canvas.restore();
}
@override
......
......@@ -21,8 +21,9 @@ export 'package:flutter/rendering.dart' show
TableColumnWidth;
class TableRow {
const TableRow({ this.key, this.children });
const TableRow({ this.key, this.decoration, this.children });
final LocalKey key;
final Decoration decoration;
final List<Widget> children;
}
......@@ -39,13 +40,15 @@ class _TableElementRow {
class Table extends RenderObjectWidget {
Table({
Key key,
this.children: const <TableRow>[],
List<TableRow> children: const <TableRow>[],
this.columnWidths,
this.defaultColumnWidth: const FlexColumnWidth(1.0),
this.border,
this.defaultVerticalAlignment: TableCellVerticalAlignment.top,
this.textBaseline
}) : super(key: key) {
}) : children = children,
_rowDecorations = children.map/*<Decoration>*/((TableRow row) => row.decoration).toList(),
super(key: key) {
assert(children != null);
assert(defaultColumnWidth != null);
assert(defaultVerticalAlignment != null);
......@@ -63,6 +66,8 @@ class Table extends RenderObjectWidget {
final TableCellVerticalAlignment defaultVerticalAlignment;
final TextBaseline textBaseline;
final List<Decoration> _rowDecorations;
@override
_TableElement createElement() => new _TableElement(this);
......@@ -74,6 +79,7 @@ class Table extends RenderObjectWidget {
columnWidths: columnWidths,
defaultColumnWidth: defaultColumnWidth,
border: border,
rowDecorations: _rowDecorations,
defaultVerticalAlignment: defaultVerticalAlignment,
textBaseline: textBaseline
);
......@@ -87,6 +93,7 @@ class Table extends RenderObjectWidget {
..columnWidths = columnWidths
..defaultColumnWidth = defaultColumnWidth
..border = border
..rowDecorations = _rowDecorations
..defaultVerticalAlignment = defaultVerticalAlignment
..textBaseline = textBaseline;
}
......
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