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}) {
if (children.isEmpty || _context.firstChild >= children.length) {
box = PdfRect.fromPoints(PdfPoint.zero, constraints.smallest);
return;
}
BoxConstraints? childConstraints;
double? mainAxisLimit = 0.0;
var flipMainAxis = false;
var flipCrossAxis = false;
final textDirection = Directionality.of(context);
switch (direction) {
case Axis.horizontal:
childConstraints = BoxConstraints(maxWidth: constraints.maxWidth);
mainAxisLimit = constraints.maxWidth;
if (textDirection == TextDirection.rtl) {
flipMainAxis = true;
}
if (verticalDirection == VerticalDirection.down) {
flipCrossAxis = true;
}
break;
case Axis.vertical:
childConstraints = BoxConstraints(maxHeight: constraints.maxHeight);
mainAxisLimit = constraints.maxHeight;
if (verticalDirection == VerticalDirection.down) {
flipMainAxis = true;
}
if (textDirection == TextDirection.rtl) {
flipCrossAxis = true;
}
break;
}
final runMetrics = <_RunMetrics>[];
final childRunMetrics = <Widget, int>{};
var mainAxisExtent = 0.0;
var crossAxisExtent = 0.0;
var runMainAxisExtent = 0.0;
var runCrossAxisExtent = 0.0;
var childCount = 0;
for (final child in children.sublist(_context.firstChild)) {
child.layout(context, childConstraints, parentUsesSize: true);
final childMainAxisExtent = _getMainAxisExtent(child)!;
final childCrossAxisExtent = _getCrossAxisExtent(child)!;
if (childCount > 0 &&
runMainAxisExtent + spacing + childMainAxisExtent > mainAxisLimit) {
mainAxisExtent = math.max(mainAxisExtent, runMainAxisExtent);
crossAxisExtent += runCrossAxisExtent;
if (runMetrics.isNotEmpty) {
crossAxisExtent += runSpacing;
}
runMetrics.add(
_RunMetrics(runMainAxisExtent, runCrossAxisExtent, childCount));
runMainAxisExtent = 0.0;
runCrossAxisExtent = 0.0;
childCount = 0;
}
runMainAxisExtent += childMainAxisExtent;
if (childCount > 0) {
runMainAxisExtent += spacing;
}
runCrossAxisExtent = math.max(runCrossAxisExtent, childCrossAxisExtent);
childCount += 1;
childRunMetrics[child] = runMetrics.length;
}
if (childCount > 0) {
mainAxisExtent = math.max(mainAxisExtent, runMainAxisExtent);
crossAxisExtent += runCrossAxisExtent;
if (runMetrics.isNotEmpty) {
crossAxisExtent += runSpacing;
}
runMetrics
.add(_RunMetrics(runMainAxisExtent, runCrossAxisExtent, childCount));
}
final runCount = runMetrics.length;
assert(runCount > 0);
double? containerMainAxisExtent = 0.0;
double? containerCrossAxisExtent = 0.0;
switch (direction) {
case Axis.horizontal:
box = PdfRect.fromPoints(PdfPoint.zero,
constraints.constrain(PdfPoint(mainAxisExtent, crossAxisExtent)));
containerMainAxisExtent = box!.width;
containerCrossAxisExtent = box!.height;
break;
case Axis.vertical:
box = PdfRect.fromPoints(PdfPoint.zero,
constraints.constrain(PdfPoint(crossAxisExtent, mainAxisExtent)));
containerMainAxisExtent = box!.height;
containerCrossAxisExtent = box!.width;
break;
}
final crossAxisFreeSpace =
math.max(0.0, containerCrossAxisExtent - crossAxisExtent);
var runLeadingSpace = 0.0;
var runBetweenSpace = 0.0;
switch (runAlignment) {
case WrapAlignment.start:
break;
case WrapAlignment.end:
runLeadingSpace = crossAxisFreeSpace;
break;
case WrapAlignment.center:
runLeadingSpace = crossAxisFreeSpace / 2.0;
break;
case WrapAlignment.spaceBetween:
runBetweenSpace =
runCount > 1 ? crossAxisFreeSpace / (runCount - 1) : 0.0;
break;
case WrapAlignment.spaceAround:
runBetweenSpace = crossAxisFreeSpace / runCount;
runLeadingSpace = runBetweenSpace / 2.0;
break;
case WrapAlignment.spaceEvenly:
runBetweenSpace = crossAxisFreeSpace / (runCount + 1);
runLeadingSpace = runBetweenSpace;
break;
}
runBetweenSpace += runSpacing;
var crossAxisOffset = flipCrossAxis
? containerCrossAxisExtent - runLeadingSpace
: runLeadingSpace;
_context.lastChild = _context.firstChild;
for (var i = 0; i < runCount; ++i) {
final metrics = runMetrics[i];
final runMainAxisExtent = metrics.mainAxisExtent;
final runCrossAxisExtent = metrics.crossAxisExtent;
final childCount = metrics.childCount;
final mainAxisFreeSpace =
math.max(0.0, containerMainAxisExtent - runMainAxisExtent);
var childLeadingSpace = 0.0;
var childBetweenSpace = 0.0;
switch (alignment) {
case WrapAlignment.start:
break;
case WrapAlignment.end:
childLeadingSpace = mainAxisFreeSpace;
break;
case WrapAlignment.center:
childLeadingSpace = mainAxisFreeSpace / 2.0;
break;
case WrapAlignment.spaceBetween:
childBetweenSpace =
childCount > 1 ? mainAxisFreeSpace / (childCount - 1) : 0.0;
break;
case WrapAlignment.spaceAround:
childBetweenSpace = mainAxisFreeSpace / childCount;
childLeadingSpace = childBetweenSpace / 2.0;
break;
case WrapAlignment.spaceEvenly:
childBetweenSpace = mainAxisFreeSpace / (childCount + 1);
childLeadingSpace = childBetweenSpace;
break;
}
childBetweenSpace += spacing;
var childMainPosition = flipMainAxis
? containerMainAxisExtent - childLeadingSpace
: childLeadingSpace;
if (flipCrossAxis) {
crossAxisOffset -= runCrossAxisExtent;
}
if (crossAxisOffset < -.01 ||
crossAxisOffset + runCrossAxisExtent >
containerCrossAxisExtent + .01) {
break;
}
var currentWidget = _context.lastChild;
for (final child in children.sublist(currentWidget)) {
final runIndex = childRunMetrics[child];
if (runIndex != i) {
break;
}
currentWidget++;
final childMainAxisExtent = _getMainAxisExtent(child);
final childCrossAxisExtent = _getCrossAxisExtent(child)!;
final childCrossAxisOffset = _getChildCrossAxisOffset(
flipCrossAxis, runCrossAxisExtent, childCrossAxisExtent);
if (flipMainAxis) {
childMainPosition -= childMainAxisExtent!;
}
child.box = PdfRect.fromPoints(
_getOffset(
childMainPosition, crossAxisOffset + childCrossAxisOffset),
child.box!.size);
if (flipMainAxis) {
childMainPosition -= childBetweenSpace;
} else {
childMainPosition += childMainAxisExtent! + childBetweenSpace;
}
}
if (flipCrossAxis) {
crossAxisOffset -= runBetweenSpace;
} else {
crossAxisOffset += runCrossAxisExtent + runBetweenSpace;
}
_context.lastChild = currentWidget;
}
}