layout method
void
layout(
- Context context,
- BoxConstraints constraints, {
- bool parentUsesSize = false,
override
First widget pass to calculate the children layout and bounding box
Implementation
@override
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
// Compute required width for all row/columns width flex
final flex = <double?>[];
_widths.clear();
_heights.clear();
var index = 0;
for (final row in children) {
var n = 0;
for (final child in row.children) {
final columnWidth = columnWidths != null && columnWidths![n] != null
? columnWidths![n]!
: defaultColumnWidth;
final columnLayout = columnWidth.layout(child, context, constraints);
if (flex.length < n + 1) {
flex.add(columnLayout.flex);
_widths.add(columnLayout.width);
} else {
if (columnLayout.flex! > 0) {
flex[n] = math.max(flex[n]!, columnLayout.flex!);
}
_widths[n] = math.max(_widths[n]!, columnLayout.width!);
}
n++;
}
}
if (_widths.isEmpty) {
box = PdfRect.fromPoints(PdfPoint.zero, constraints.smallest);
return;
}
final maxWidth = _widths.reduce((double? a, double? b) => a! + b!);
// Compute column widths using flex and estimated width
if (constraints.hasBoundedWidth) {
final totalFlex = flex.reduce((double? a, double? b) => a! + b!)!;
var flexSpace = 0.0;
for (var n = 0; n < _widths.length; n++) {
if (flex[n] == 0.0) {
final newWidth = _widths[n]! / maxWidth! * constraints.maxWidth;
if ((tableWidth == TableWidth.max && totalFlex == 0.0) ||
newWidth < _widths[n]!) {
_widths[n] = newWidth;
}
flexSpace += _widths[n]!;
}
}
final spacePerFlex = totalFlex > 0.0
? ((constraints.maxWidth - flexSpace) / totalFlex)
: double.nan;
for (var n = 0; n < _widths.length; n++) {
if (flex[n]! > 0.0) {
final newWidth = spacePerFlex * flex[n]!;
_widths[n] = newWidth;
}
}
}
final totalWidth = _widths.reduce((double? a, double? b) => a! + b!)!;
// Compute final widths
var totalHeight = 0.0;
index = 0;
for (final row in children) {
if (index++ < _context.firstLine && !row.repeat) {
continue;
}
var n = 0;
var x = 0.0;
var lineHeight = 0.0;
for (final child in row.children) {
final childConstraints = BoxConstraints.tightFor(width: _widths[n]);
child.layout(context, childConstraints);
assert(child.box != null);
child.box =
PdfRect(x, totalHeight, child.box!.width, child.box!.height);
x += _widths[n]!;
lineHeight = math.max(lineHeight, child.box!.height);
n++;
}
final align = row.verticalAlignment ?? defaultVerticalAlignment;
if (align == TableCellVerticalAlignment.full) {
// Compute the layout again to give the full height to all cells
n = 0;
x = 0;
for (final child in row.children) {
final childConstraints =
BoxConstraints.tightFor(width: _widths[n], height: lineHeight);
child.layout(context, childConstraints);
assert(child.box != null);
child.box =
PdfRect(x, totalHeight, child.box!.width, child.box!.height);
x += _widths[n]!;
n++;
}
}
if (totalHeight + lineHeight > constraints.maxHeight) {
index--;
break;
}
totalHeight += lineHeight;
_heights.add(lineHeight);
}
_context.lastLine = index;
// Compute final y position
index = 0;
var heightIndex = 0;
for (final row in children) {
if (index++ < _context.firstLine && !row.repeat) {
continue;
}
final align = row.verticalAlignment ?? defaultVerticalAlignment;
for (final child in row.children) {
double? childY;
switch (align) {
case TableCellVerticalAlignment.bottom:
childY = totalHeight - child.box!.y - _getHeight(heightIndex);
break;
case TableCellVerticalAlignment.middle:
childY = totalHeight -
child.box!.y -
(_getHeight(heightIndex) + child.box!.height) / 2;
break;
case TableCellVerticalAlignment.top:
case TableCellVerticalAlignment.full:
childY = totalHeight - child.box!.y - child.box!.height;
break;
}
child.box = PdfRect(
child.box!.x,
childY,
child.box!.width,
child.box!.height,
);
}
if (index >= _context.lastLine) {
break;
}
heightIndex++;
}
box = PdfRect(0, 0, totalWidth, totalHeight);
}