- override
Do the work of computing the layout for this render object.
Do not call this function directly: call layout
instead. This function
is called by layout
when there is actually work to be done by this
render object during layout. The layout constraints provided by your
parent are available via the constraints
getter.
If sizedByParent
is true, then this function should not actually change
the dimensions of this render object. Instead, that work should be done by
performResize
. If sizedByParent
is false, then this function should
both change the dimensions of this render object and instruct its children
to layout.
In implementing this function, you must call layout
on each of your
children, passing true for parentUsesSize if your layout information is
dependent on your child's layout information. Passing true for
parentUsesSize ensures that this render object will undergo layout if the
child undergoes layout. Otherwise, the child can changes its layout
information without informing this render object.
Source
@override void performLayout() { assert(_children.length == rows * columns); if (rows * columns == 0) { // TODO(ianh): if columns is zero, this should be zero width // TODO(ianh): if columns is not zero, this should be based on the column width specifications size = constraints.constrain(const Size(0.0, 0.0)); return; } 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; assert(!positions.any((double value) => value == null)); _baselineDistance = null; // then, lay out each row double rowTop = 0.0; for (int y = 0; y < rows; y += 1) { _rowTops.add(rowTop); double rowHeight = 0.0; bool haveBaseline = false; double beforeBaselineDistance = 0.0; double afterBaselineDistance = 0.0; List<double> baselines = new List<double>(columns); for (int x = 0; x < columns; x += 1) { final int xy = x + y * columns; RenderBox child = _children[xy]; if (child != null) { TableCellParentData childParentData = child.parentData; assert(childParentData != null); childParentData.x = x; childParentData.y = y; switch (childParentData.verticalAlignment ?? defaultVerticalAlignment) { case TableCellVerticalAlignment.baseline: assert(textBaseline != null); child.layout(new BoxConstraints.tightFor(width: widths[x]), parentUsesSize: true); double childBaseline = child.getDistanceToBaseline(textBaseline, onlyReal: true); if (childBaseline != null) { beforeBaselineDistance = math.max(beforeBaselineDistance, childBaseline); afterBaselineDistance = math.max(afterBaselineDistance, child.size.height - childBaseline); baselines[x] = childBaseline; haveBaseline = true; } else { rowHeight = math.max(rowHeight, child.size.height); childParentData.offset = new Offset(positions[x], rowTop); } break; case TableCellVerticalAlignment.top: case TableCellVerticalAlignment.middle: case TableCellVerticalAlignment.bottom: child.layout(new BoxConstraints.tightFor(width: widths[x]), parentUsesSize: true); rowHeight = math.max(rowHeight, child.size.height); break; case TableCellVerticalAlignment.fill: break; } } } if (haveBaseline) { if (y == 0) _baselineDistance = beforeBaselineDistance; rowHeight = math.max(rowHeight, beforeBaselineDistance + afterBaselineDistance); } for (int x = 0; x < columns; x += 1) { final int xy = x + y * columns; RenderBox child = _children[xy]; if (child != null) { final TableCellParentData childParentData = child.parentData; switch (childParentData.verticalAlignment ?? defaultVerticalAlignment) { case TableCellVerticalAlignment.baseline: if (baselines[x] != null) childParentData.offset = new Offset(positions[x], rowTop + beforeBaselineDistance - baselines[x]); break; case TableCellVerticalAlignment.top: childParentData.offset = new Offset(positions[x], rowTop); break; case TableCellVerticalAlignment.middle: childParentData.offset = new Offset(positions[x], rowTop + (rowHeight - child.size.height) / 2.0); break; case TableCellVerticalAlignment.bottom: childParentData.offset = new Offset(positions[x], rowTop + rowHeight - child.size.height); break; case TableCellVerticalAlignment.fill: child.layout(new BoxConstraints.tightFor(width: widths[x], height: rowHeight)); childParentData.offset = new Offset(positions[x], rowTop); break; } } } rowTop += rowHeight; } _rowTops.add(rowTop); size = constraints.constrain(new Size(positions.last + widths.last, rowTop)); assert(_rowTops.length == rows + 1); }