performBoxLayout method
Perform layout with typed box constraints
Subclasses override this instead of performLayout. The default implementation sizes to the maxima, treating an unbounded axis as the corresponding lower bound.
Implementation
@override
void performBoxLayout(BoxConstraints constraints) {
final columns = _content.fold<int>(
0,
(count, row) => math.max(count, row.length),
);
if (columns == 0 || _content.isEmpty) {
_columnWidths = const <int>[];
_rowHeights = const <int>[];
_cells = const <_TableCellLayout>[];
_gridWidth = 0;
size = Size(
constraints.constrainWidth(0),
constraints.constrainHeight(0),
);
return;
}
final intrinsic = List<int>.filled(columns, 1);
for (final row in _content) {
for (var column = 0; column < row.length; column++) {
final span = row[column];
if (span == null) continue;
final layout = const TextLayoutEngine().layout(
span,
const BoxConstraints(),
);
intrinsic[column] = math.max(intrinsic[column], layout.maxLineWidth);
}
}
final outer = _outerBorder && _showBorders ? 2 : 0;
final separators = columns - 1;
final separatorWidth = _showBorders ? 1 : _columnGap;
final structural =
outer + separators * separatorWidth + columns * _cellPaddingX * 2;
final intrinsicContent = intrinsic.fold<int>(
0,
(sum, value) => sum + value,
);
final boundedContent = constraints.maxWidth == null
? intrinsicContent
: math.max(columns, constraints.maxWidth! - structural);
if (intrinsicContent < boundedContent) {
_columnWidths = _columnWidthMode == TextTableColumnWidthMode.full
? _expandWidths(intrinsic, boundedContent)
: List<int>.unmodifiable(intrinsic);
} else if (intrinsicContent > boundedContent &&
_wrapMode != TextTableWrapMode.none) {
_columnWidths = _fitWidths(intrinsic, boundedContent, _columnFitter);
} else {
_columnWidths = List<int>.unmodifiable(intrinsic);
}
final cells = <_TableCellLayout>[];
final rowHeights = <int>[];
var sourceBase = 0;
for (var rowIndex = 0; rowIndex < _content.length; rowIndex++) {
final row = _content[rowIndex];
var rowHeight = 1 + _cellPaddingY * 2;
for (var column = 0; column < columns; column++) {
final span = column < row.length ? row[column] : null;
final effective = span ?? const TextSpan(text: '');
final layout = _layoutCell(effective, _columnWidths[column], _wrapMode);
cells.add(
_TableCellLayout(
row: rowIndex,
column: column,
layout: layout,
sourceBase: sourceBase,
),
);
rowHeight = math.max(rowHeight, layout.lineCount + _cellPaddingY * 2);
sourceBase += layout.text.length;
if (column < columns - 1) sourceBase++;
}
rowHeights.add(rowHeight);
if (rowIndex < _content.length - 1) sourceBase++;
}
_rowHeights = List<int>.unmodifiable(rowHeights);
_cells = List<_TableCellLayout>.unmodifiable(cells);
final width =
structural + _columnWidths.fold<int>(0, (sum, value) => sum + value);
_gridWidth = width;
final horizontalRules = _showBorders
? (_outerBorder ? 2 : 0) + (_content.length - 1)
: 0;
final height =
horizontalRules + rowHeights.fold<int>(0, (sum, value) => sum + value);
size = Size(
constraints.constrainWidth(width),
constraints.constrainHeight(height),
);
}