layout method
layout API.
Implementation
@override
PwBox layout(Context context, BoxConstraints constraints) {
final bool horiz = direction == Axis.horizontal;
final double maxMain = horiz ? constraints.maxWidth : constraints.maxHeight;
final double maxCross = horiz ? constraints.maxHeight : constraints.maxWidth;
final bool mainBounded = horiz
? constraints.hasBoundedWidth
: constraints.hasBoundedHeight;
final List<PwBox?> boxes = List<PwBox?>.filled(children.length, null);
var allocated = 0.0;
var totalFlex = 0;
for (int i = 0; i < children.length; i++) {
final Widget raw = children[i];
final int flex = raw is Flexible ? raw.flex : 0;
if (flex > 0) {
totalFlex += flex;
continue;
}
final Widget inner = raw is Flexible ? raw.child : raw;
final BoxConstraints childCs = horiz
? BoxConstraints(
maxWidth: mainBounded ? (maxMain - allocated).clamp(0, maxMain) : double.infinity,
maxHeight: maxCross,
minHeight: crossAxisAlignment == CrossAxisAlignment.stretch
? (maxCross.isFinite ? maxCross : 0)
: 0,
)
: BoxConstraints(
maxWidth: maxCross,
minWidth: crossAxisAlignment == CrossAxisAlignment.stretch
? (maxCross.isFinite ? maxCross : 0)
: 0,
maxHeight: mainBounded
? (maxMain - allocated).clamp(0, maxMain)
: double.infinity,
);
final PwBox box = inner.layout(context, childCs);
boxes[i] = box;
allocated += horiz ? box.size.width : box.size.height;
}
final double flexSpace = mainBounded
? (maxMain - allocated).clamp(0, maxMain)
: 0;
for (int i = 0; i < children.length; i++) {
if (boxes[i] != null) {
continue;
}
final Widget raw = children[i];
final int flex = raw is Flexible ? raw.flex : 1;
final FlexFit fit = raw is Flexible ? raw.fit : FlexFit.loose;
final Widget inner = raw is Flexible ? raw.child : raw;
final double share = totalFlex <= 0 ? 0 : flexSpace * flex / totalFlex;
final BoxConstraints childCs = horiz
? BoxConstraints(
minWidth: fit == FlexFit.tight ? share : 0,
maxWidth: share,
maxHeight: maxCross,
minHeight: crossAxisAlignment == CrossAxisAlignment.stretch &&
maxCross.isFinite
? maxCross
: 0,
)
: BoxConstraints(
minHeight: fit == FlexFit.tight ? share : 0,
maxHeight: share,
maxWidth: maxCross,
minWidth: crossAxisAlignment == CrossAxisAlignment.stretch &&
maxCross.isFinite
? maxCross
: 0,
);
final PwBox box = inner.layout(context, childCs);
boxes[i] = box;
allocated += horiz ? box.size.width : box.size.height;
}
var cross = 0.0;
for (final PwBox? box in boxes) {
if (box == null) {
continue;
}
final double c = horiz ? box.size.height : box.size.width;
if (c > cross) {
cross = c;
}
}
if (crossAxisAlignment == CrossAxisAlignment.stretch && maxCross.isFinite) {
cross = maxCross;
}
final double main = mainAxisSize == MainAxisSize.max &&
mainBounded &&
allocated < maxMain
? maxMain
: allocated;
final PwSize size = constraints.constrain(
horiz ? PwSize(main, cross) : PwSize(cross, main),
);
final List<(PwBox, PwOffset)> placed = <(PwBox, PwOffset)>[];
final List<double> mains = <double>[
for (final PwBox? box in boxes)
box == null ? 0 : (horiz ? box.size.width : box.size.height),
];
var cursor = 0.0;
var gap = 0.0;
final double leftover = (main - allocated).clamp(0, double.infinity);
final bool reverseMain =
horiz && context.textDirection == TextDirection.rtl;
switch (mainAxisAlignment) {
case MainAxisAlignment.start:
cursor = reverseMain ? leftover : 0;
case MainAxisAlignment.end:
cursor = reverseMain ? 0 : leftover;
case MainAxisAlignment.center:
cursor = leftover / 2;
case MainAxisAlignment.spaceBetween:
gap = boxes.length > 1 ? leftover / (boxes.length - 1) : 0;
case MainAxisAlignment.spaceAround:
gap = boxes.isEmpty ? 0 : leftover / boxes.length;
cursor = gap / 2;
case MainAxisAlignment.spaceEvenly:
gap = leftover / (boxes.length + 1);
cursor = gap;
}
final List<int> order = <int>[
for (int i = 0; i < boxes.length; i++)
reverseMain ? boxes.length - 1 - i : i,
];
for (final int i in order) {
final PwBox box = boxes[i]!;
final double crossOff = switch (crossAxisAlignment) {
CrossAxisAlignment.start => _crossStart(
horiz: horiz,
rtl: context.textDirection == TextDirection.rtl,
size: size,
box: box,
),
CrossAxisAlignment.end => _crossEnd(
horiz: horiz,
rtl: context.textDirection == TextDirection.rtl,
size: size,
box: box,
),
CrossAxisAlignment.center => horiz
? (size.height - box.size.height) / 2
: (size.width - box.size.width) / 2,
CrossAxisAlignment.stretch => 0,
};
placed.add((
box,
horiz ? PwOffset(cursor, crossOff) : PwOffset(crossOff, cursor),
));
cursor += mains[i] + gap;
}
return GroupBox(size, placed);
}