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 horizontal = _direction == Axis.horizontal;
final maxMain = horizontal ? constraints.maxWidth : constraints.maxHeight;
final childConstraints = horizontal
? BoxConstraints(maxWidth: maxMain, maxHeight: constraints.maxHeight)
: BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: maxMain);
final runs = <_WrapRun>[];
var current = _WrapRun();
for (final child in children.whereType<RenderBox>()) {
child.layout(childConstraints);
final childMain = horizontal ? child.size.width : child.size.height;
final childCross = horizontal ? child.size.height : child.size.width;
final nextMain = current.items.isEmpty
? childMain
: current.main + _spacing + childMain;
if (maxMain != null && current.items.isNotEmpty && nextMain > maxMain) {
runs.add(current);
current = _WrapRun();
}
if (current.items.isNotEmpty) current.main += _spacing;
current
..items.add(_WrapChild(child, childMain, childCross))
..main += childMain;
if (childCross > current.cross) current.cross = childCross;
}
if (current.items.isNotEmpty) runs.add(current);
final naturalMain = runs.fold<int>(
0,
(value, run) => run.main > value ? run.main : value,
);
final naturalCross = runs.isEmpty
? 0
: runs.fold<int>(0, (value, run) => value + run.cross) +
_runSpacing * (runs.length - 1);
final width = horizontal
? constraints.constrainWidth(naturalMain)
: constraints.constrainWidth(naturalCross);
final height = horizontal
? constraints.constrainHeight(naturalCross)
: constraints.constrainHeight(naturalMain);
size = Size(width, height);
final finalMain = horizontal ? width : height;
final finalCross = horizontal ? height : width;
final runCrossSizes = runs.map((run) => run.cross).toList(growable: false);
final runOffsets = _alignedOffsets(
finalCross,
runCrossSizes,
_runSpacing,
_runAlignment,
);
for (var runIndex = 0; runIndex < runs.length; runIndex++) {
final run = runs[runIndex];
final mainOffsets = _alignedOffsets(
finalMain,
run.items.map((child) => child.main).toList(growable: false),
_spacing,
_alignment,
);
for (var index = 0; index < run.items.length; index++) {
final child = run.items[index];
final crossSlack = run.cross - child.cross;
final childCross = switch (_crossAxisAlignment) {
WrapCrossAlignment.start => 0,
WrapCrossAlignment.end => crossSlack,
WrapCrossAlignment.center => allocateExactCells(
crossSlack,
const <int>[1, 1],
)[0],
};
final main = mainOffsets[index];
final cross = runOffsets[runIndex] + childCross;
positionChild(
child.box,
horizontal ? main : cross,
horizontal ? cross : main,
);
}
}
}