Reverts "Implement computeDryBaseline for RenderWrap (#146260)" (#147692)

Reverts: flutter/flutter#146260
Initiated by: chingjun
Reason for reverting: Broke internal tests. See b/338308016
Original PR Author: LongCatIsLooong

Reviewed By: {goderbauer}

This change reverts the following previous change:
This commit is contained in:
auto-submit[bot] 2024-05-02 02:26:28 +00:00 committed by GitHub
parent 8025af0aa6
commit 706f39b0a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 185 additions and 244 deletions

View File

@ -806,8 +806,7 @@ class RenderTable extends RenderBox {
double? _baselineDistance;
@override
double? computeDistanceToActualBaseline(TextBaseline baseline) {
// returns the baseline offset of the cell in the first row with
// the lowest baseline, and uses `TableCellVerticalAlignment.baseline`.
// returns the baseline of the first cell that has a baseline in the first row
assert(!debugNeedsLayout);
return _baselineDistance;
}
@ -1027,36 +1026,6 @@ class RenderTable extends RenderBox {
return Rect.fromLTRB(0.0, _rowTops[row], size.width, _rowTops[row + 1]);
}
@override
double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
if (rows * columns == 0) {
return null;
}
final List<double> widths = _computeColumnWidths(constraints);
double? baselineOffset;
for (int col = 0; col < columns; col += 1) {
final RenderBox? child = _children[col];
final BoxConstraints childConstraints = BoxConstraints.tightFor(width: widths[col]);
if (child == null) {
continue;
}
final TableCellParentData childParentData = child.parentData! as TableCellParentData;
final double? childBaseline = switch (childParentData.verticalAlignment ?? defaultVerticalAlignment) {
TableCellVerticalAlignment.baseline => child.getDryBaseline(childConstraints, baseline),
TableCellVerticalAlignment.baseline ||
TableCellVerticalAlignment.top ||
TableCellVerticalAlignment.middle ||
TableCellVerticalAlignment.bottom ||
TableCellVerticalAlignment.fill ||
TableCellVerticalAlignment.intrinsicHeight => null,
};
if (childBaseline != null && (baselineOffset == null || baselineOffset < childBaseline)) {
baselineOffset = childBaseline;
}
}
return baselineOffset;
}
@override
@protected
Size computeDryLayout(covariant BoxConstraints constraints) {

View File

@ -11,41 +11,6 @@ import 'layer.dart';
import 'layout_helper.dart';
import 'object.dart';
typedef _NextChild = RenderBox? Function(RenderBox child);
typedef _PositionChild = void Function(Offset offset, RenderBox child);
typedef _GetChildSize = Size Function(RenderBox child);
// A 2D vector that uses a [RenderWrap]'s main axis and cross axis as its first and second coordinate axes.
// It represents the same vector as (double mainAxisExtent, double crossAxisExtent).
extension type const _AxisSize._(Size _size) {
_AxisSize({ required double mainAxisExtent, required double crossAxisExtent }) : this._(Size(mainAxisExtent, crossAxisExtent));
_AxisSize.fromSize({ required Size size, required Axis direction }) : this._(_convert(size, direction));
static const _AxisSize empty = _AxisSize._(Size.zero);
static Size _convert(Size size, Axis direction) {
return switch (direction) {
Axis.horizontal => size,
Axis.vertical => size.flipped,
};
}
double get mainAxisExtent => _size.width;
double get crossAxisExtent => _size.height;
Size toSize(Axis direction) => _convert(_size, direction);
_AxisSize applyConstraints(BoxConstraints constraints, Axis direction) {
final BoxConstraints effectiveConstraints = switch (direction) {
Axis.horizontal => constraints,
Axis.vertical => constraints.flipped,
};
return _AxisSize._(effectiveConstraints.constrain(_size));
}
_AxisSize get flipped => _AxisSize._(_size.flipped);
_AxisSize operator +(_AxisSize other) => _AxisSize._(Size(_size.width + other._size.width, math.max(_size.height, other._size.height)));
_AxisSize operator -(_AxisSize other) => _AxisSize._(Size(_size.width - other._size.width, _size.height - other._size.height));
}
/// How [Wrap] should align objects.
///
/// Used both to align children within a run in the main axis as well as to
@ -81,22 +46,7 @@ enum WrapAlignment {
/// Place the free space evenly between the objects as well as before and
/// after the first and last objects.
spaceEvenly;
(double leadingSpace, double betweenSpace) _distributeSpace(double freeSpace, double itemSpacing, int itemCount, bool flipped) {
assert(itemCount > 0);
return switch (this) {
WrapAlignment.start => (flipped ? freeSpace : 0.0, itemSpacing),
WrapAlignment.end => WrapAlignment.start._distributeSpace(freeSpace, itemSpacing, itemCount, !flipped),
WrapAlignment.spaceBetween when itemCount < 2 => WrapAlignment.start._distributeSpace(freeSpace, itemSpacing, itemCount, flipped),
WrapAlignment.center => (freeSpace / 2.0, itemSpacing),
WrapAlignment.spaceBetween => (0, freeSpace / (itemCount - 1) + itemSpacing),
WrapAlignment.spaceAround => (freeSpace / itemCount / 2, freeSpace / itemCount + itemSpacing),
WrapAlignment.spaceEvenly => (freeSpace / (itemCount + 1), freeSpace / (itemCount + 1) + itemSpacing),
};
}
spaceEvenly,
}
/// Who [Wrap] should align children within a run in the cross axis.
@ -123,48 +73,23 @@ enum WrapCrossAlignment {
/// Place the children as close to the middle of the run in the cross axis as
/// possible.
center;
center,
// TODO(ianh): baseline.
WrapCrossAlignment get _flipped => switch (this) {
WrapCrossAlignment.start => WrapCrossAlignment.end,
WrapCrossAlignment.end => WrapCrossAlignment.start,
WrapCrossAlignment.center => WrapCrossAlignment.center,
};
double get _alignment => switch (this) {
WrapCrossAlignment.start => 0,
WrapCrossAlignment.end => 1,
WrapCrossAlignment.center => 0.5,
};
}
class _RunMetrics {
_RunMetrics(this.leadingChild, this.axisSize);
_RunMetrics(this.mainAxisExtent, this.crossAxisExtent, this.childCount);
_AxisSize axisSize;
int childCount = 1;
RenderBox leadingChild;
// Look ahead, creates a new run if incorporating the child would exceed the allowed line width.
_RunMetrics? tryAddingNewChild(RenderBox child, _AxisSize childSize, bool flipMainAxis, double spacing, double maxMainExtent) {
final bool needsNewRun = axisSize.mainAxisExtent + childSize.mainAxisExtent + spacing - maxMainExtent > precisionErrorTolerance;
if (needsNewRun) {
return _RunMetrics(child, childSize);
} else {
axisSize += childSize + _AxisSize(mainAxisExtent: spacing, crossAxisExtent: 0.0);
childCount += 1;
if (flipMainAxis) {
leadingChild = child;
}
return null;
}
}
final double mainAxisExtent;
final double crossAxisExtent;
final int childCount;
}
/// Parent data for use with [RenderWrap].
class WrapParentData extends ContainerBoxParentData<RenderBox> { }
class WrapParentData extends ContainerBoxParentData<RenderBox> {
int _runIndex = 0;
}
/// Displays its children in multiple horizontal or vertical runs.
///
@ -549,42 +474,16 @@ class RenderWrap extends RenderBox
};
}
(bool flipHorizontal, bool flipVertical) get _areAxesFlipped {
final bool flipHorizontal = switch (textDirection ?? TextDirection.ltr) {
TextDirection.ltr => false,
TextDirection.rtl => true,
};
final bool flipVertical = switch (verticalDirection) {
VerticalDirection.down => false,
VerticalDirection.up => true,
};
return switch (direction) {
Axis.horizontal => (flipHorizontal, flipVertical),
Axis.vertical => (flipVertical, flipHorizontal),
double _getChildCrossAxisOffset(bool flipCrossAxis, double runCrossAxisExtent, double childCrossAxisExtent) {
final double freeSpace = runCrossAxisExtent - childCrossAxisExtent;
return switch (crossAxisAlignment) {
WrapCrossAlignment.start => flipCrossAxis ? freeSpace : 0.0,
WrapCrossAlignment.end => flipCrossAxis ? 0.0 : freeSpace,
WrapCrossAlignment.center => freeSpace / 2.0,
};
}
@override
double? computeDryBaseline(covariant BoxConstraints constraints, TextBaseline baseline) {
if (firstChild == null) {
return null;
}
final BoxConstraints childConstraints = switch (direction) {
Axis.horizontal => BoxConstraints(maxWidth: constraints.maxWidth),
Axis.vertical => BoxConstraints(maxHeight: constraints.maxHeight),
};
final (_AxisSize childrenAxisSize, List<_RunMetrics> runMetrics) = _computeRuns(constraints, ChildLayoutHelper.dryLayoutChild);
final _AxisSize containerAxisSize = childrenAxisSize.applyConstraints(constraints, direction);
BaselineOffset baselineOffset = BaselineOffset.noBaseline;
void findHighestBaseline(Offset offset, RenderBox child) {
baselineOffset = baselineOffset.minOf(BaselineOffset(child.getDryBaseline(childConstraints, baseline)) + offset.dy);
}
Size getChildSize(RenderBox child) => child.getDryLayout(childConstraints);
_positionChildren(runMetrics, childrenAxisSize, containerAxisSize, findHighestBaseline, getChildSize);
return baselineOffset.offset;
}
bool _hasVisualOverflow = false;
@override
@protected
@ -633,97 +532,184 @@ class RenderWrap extends RenderBox
});
}
static Size _getChildSize(RenderBox child) => child.size;
static void _setChildPosition(Offset offset, RenderBox child) {
(child.parentData! as WrapParentData).offset = offset;
}
bool _hasVisualOverflow = false;
@override
void performLayout() {
final BoxConstraints constraints = this.constraints;
assert(_debugHasNecessaryDirections);
if (firstChild == null) {
_hasVisualOverflow = false;
RenderBox? child = firstChild;
if (child == null) {
size = constraints.smallest;
_hasVisualOverflow = false;
return;
}
final (_AxisSize childrenAxisSize, List<_RunMetrics> runMetrics) = _computeRuns(constraints, ChildLayoutHelper.layoutChild);
final _AxisSize containerAxisSize = childrenAxisSize.applyConstraints(constraints, direction);
size = containerAxisSize.toSize(direction);
final _AxisSize freeAxisSize = containerAxisSize - childrenAxisSize;
_hasVisualOverflow = freeAxisSize.mainAxisExtent < 0.0 || freeAxisSize.crossAxisExtent < 0.0;
_positionChildren(runMetrics, freeAxisSize, containerAxisSize, _setChildPosition, _getChildSize);
}
(_AxisSize childrenSize, List<_RunMetrics> runMetrics) _computeRuns(BoxConstraints constraints, ChildLayouter layoutChild) {
assert(firstChild != null);
final (BoxConstraints childConstraints, double mainAxisLimit) = switch (direction) {
Axis.horizontal => (BoxConstraints(maxWidth: constraints.maxWidth), constraints.maxWidth),
Axis.vertical => (BoxConstraints(maxHeight: constraints.maxHeight), constraints.maxHeight),
};
final (bool flipMainAxis, _) = _areAxesFlipped;
final double spacing = this.spacing;
final List<_RunMetrics> runMetrics = <_RunMetrics>[];
_RunMetrics? currentRun;
_AxisSize childrenAxisSize = _AxisSize.empty;
for (RenderBox? child = firstChild; child != null; child = childAfter(child)) {
final _AxisSize childSize = _AxisSize.fromSize(size: layoutChild(child, childConstraints), direction: direction);
final _RunMetrics? newRun = currentRun == null
? _RunMetrics(child, childSize)
: currentRun.tryAddingNewChild(child, childSize, flipMainAxis, spacing, mainAxisLimit);
if (newRun != null) {
runMetrics.add(newRun);
childrenAxisSize += currentRun?.axisSize.flipped ?? _AxisSize.empty;
currentRun = newRun;
}
final BoxConstraints childConstraints;
double mainAxisLimit = 0.0;
bool flipMainAxis = false;
bool flipCrossAxis = false;
switch (direction) {
case Axis.horizontal:
childConstraints = BoxConstraints(maxWidth: constraints.maxWidth);
mainAxisLimit = constraints.maxWidth;
if (textDirection == TextDirection.rtl) {
flipMainAxis = true;
}
if (verticalDirection == VerticalDirection.up) {
flipCrossAxis = true;
}
case Axis.vertical:
childConstraints = BoxConstraints(maxHeight: constraints.maxHeight);
mainAxisLimit = constraints.maxHeight;
if (verticalDirection == VerticalDirection.up) {
flipMainAxis = true;
}
if (textDirection == TextDirection.rtl) {
flipCrossAxis = true;
}
}
assert(runMetrics.isNotEmpty);
final double totalRunSpacing = runSpacing * (runMetrics.length - 1);
childrenAxisSize += _AxisSize(mainAxisExtent: totalRunSpacing, crossAxisExtent: 0.0) + currentRun!.axisSize.flipped;
return (childrenAxisSize.flipped, runMetrics);
}
void _positionChildren(List<_RunMetrics> runMetrics, _AxisSize freeAxisSize, _AxisSize containerAxisSize, _PositionChild positionChild, _GetChildSize getChildSize) {
assert(runMetrics.isNotEmpty);
final double spacing = this.spacing;
final double crossAxisFreeSpace = math.max(0.0, freeAxisSize.crossAxisExtent);
final (bool flipMainAxis, bool flipCrossAxis) = _areAxesFlipped;
final WrapCrossAlignment effectiveCrossAlignment = flipCrossAxis ? crossAxisAlignment._flipped : crossAxisAlignment;
final (double runLeadingSpace, double runBetweenSpace) = runAlignment._distributeSpace(
crossAxisFreeSpace,
runSpacing,
runMetrics.length,
flipCrossAxis,
);
final _NextChild nextChild = flipMainAxis ? childBefore : childAfter;
double runCrossAxisOffset = runLeadingSpace;
final Iterable<_RunMetrics> runs = flipCrossAxis ? runMetrics.reversed : runMetrics;
for (final _RunMetrics run in runs) {
final double runCrossAxisExtent = run.axisSize.crossAxisExtent;
final int childCount = run.childCount;
final double mainAxisFreeSpace = math.max(0.0, containerAxisSize.mainAxisExtent - run.axisSize.mainAxisExtent);
final (double childLeadingSpace, double childBetweenSpace) = alignment._distributeSpace(mainAxisFreeSpace, spacing, childCount, flipMainAxis);
double childMainAxisOffset = childLeadingSpace;
int remainingChildCount = run.childCount;
for (RenderBox? child = run.leadingChild; child != null && remainingChildCount > 0; child = nextChild(child), remainingChildCount -= 1) {
final _AxisSize(mainAxisExtent: double childMainAxisExtent, crossAxisExtent: double childCrossAxisExtent) = _AxisSize.fromSize(size: getChildSize(child), direction: direction);
final double childCrossAxisOffset = effectiveCrossAlignment._alignment * (runCrossAxisExtent - childCrossAxisExtent);
positionChild(_getOffset(childMainAxisOffset, runCrossAxisOffset + childCrossAxisOffset), child);
childMainAxisOffset += childMainAxisExtent + childBetweenSpace;
final double runSpacing = this.runSpacing;
final List<_RunMetrics> runMetrics = <_RunMetrics>[];
double mainAxisExtent = 0.0;
double crossAxisExtent = 0.0;
double runMainAxisExtent = 0.0;
double runCrossAxisExtent = 0.0;
int childCount = 0;
while (child != null) {
child.layout(childConstraints, parentUsesSize: true);
final double childMainAxisExtent = _getMainAxisExtent(child.size);
final double childCrossAxisExtent = _getCrossAxisExtent(child.size);
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;
final WrapParentData childParentData = child.parentData! as WrapParentData;
childParentData._runIndex = runMetrics.length;
child = childParentData.nextSibling;
}
if (childCount > 0) {
mainAxisExtent = math.max(mainAxisExtent, runMainAxisExtent);
crossAxisExtent += runCrossAxisExtent;
if (runMetrics.isNotEmpty) {
crossAxisExtent += runSpacing;
}
runMetrics.add(_RunMetrics(runMainAxisExtent, runCrossAxisExtent, childCount));
}
final int runCount = runMetrics.length;
assert(runCount > 0);
double containerMainAxisExtent = 0.0;
double containerCrossAxisExtent = 0.0;
switch (direction) {
case Axis.horizontal:
size = constraints.constrain(Size(mainAxisExtent, crossAxisExtent));
containerMainAxisExtent = size.width;
containerCrossAxisExtent = size.height;
case Axis.vertical:
size = constraints.constrain(Size(crossAxisExtent, mainAxisExtent));
containerMainAxisExtent = size.height;
containerCrossAxisExtent = size.width;
}
_hasVisualOverflow = containerMainAxisExtent < mainAxisExtent || containerCrossAxisExtent < crossAxisExtent;
final double crossAxisFreeSpace = math.max(0.0, containerCrossAxisExtent - crossAxisExtent);
double runLeadingSpace = 0.0;
double runBetweenSpace = 0.0;
switch (runAlignment) {
case WrapAlignment.start:
break;
case WrapAlignment.end:
runLeadingSpace = crossAxisFreeSpace;
case WrapAlignment.center:
runLeadingSpace = crossAxisFreeSpace / 2.0;
case WrapAlignment.spaceBetween:
runBetweenSpace = runCount > 1 ? crossAxisFreeSpace / (runCount - 1) : 0.0;
case WrapAlignment.spaceAround:
runBetweenSpace = crossAxisFreeSpace / runCount;
runLeadingSpace = runBetweenSpace / 2.0;
case WrapAlignment.spaceEvenly:
runBetweenSpace = crossAxisFreeSpace / (runCount + 1);
runLeadingSpace = runBetweenSpace;
}
runBetweenSpace += runSpacing;
double crossAxisOffset = flipCrossAxis ? containerCrossAxisExtent - runLeadingSpace : runLeadingSpace;
child = firstChild;
for (int i = 0; i < runCount; ++i) {
final _RunMetrics metrics = runMetrics[i];
final double runMainAxisExtent = metrics.mainAxisExtent;
final double runCrossAxisExtent = metrics.crossAxisExtent;
final int childCount = metrics.childCount;
final double mainAxisFreeSpace = math.max(0.0, containerMainAxisExtent - runMainAxisExtent);
double childLeadingSpace = 0.0;
double childBetweenSpace = 0.0;
switch (alignment) {
case WrapAlignment.start:
break;
case WrapAlignment.end:
childLeadingSpace = mainAxisFreeSpace;
case WrapAlignment.center:
childLeadingSpace = mainAxisFreeSpace / 2.0;
case WrapAlignment.spaceBetween:
childBetweenSpace = childCount > 1 ? mainAxisFreeSpace / (childCount - 1) : 0.0;
case WrapAlignment.spaceAround:
childBetweenSpace = mainAxisFreeSpace / childCount;
childLeadingSpace = childBetweenSpace / 2.0;
case WrapAlignment.spaceEvenly:
childBetweenSpace = mainAxisFreeSpace / (childCount + 1);
childLeadingSpace = childBetweenSpace;
}
childBetweenSpace += spacing;
double childMainPosition = flipMainAxis ? containerMainAxisExtent - childLeadingSpace : childLeadingSpace;
if (flipCrossAxis) {
crossAxisOffset -= runCrossAxisExtent;
}
while (child != null) {
final WrapParentData childParentData = child.parentData! as WrapParentData;
if (childParentData._runIndex != i) {
break;
}
final double childMainAxisExtent = _getMainAxisExtent(child.size);
final double childCrossAxisExtent = _getCrossAxisExtent(child.size);
final double childCrossAxisOffset = _getChildCrossAxisOffset(flipCrossAxis, runCrossAxisExtent, childCrossAxisExtent);
if (flipMainAxis) {
childMainPosition -= childMainAxisExtent;
}
childParentData.offset = _getOffset(childMainPosition, crossAxisOffset + childCrossAxisOffset);
if (flipMainAxis) {
childMainPosition -= childBetweenSpace;
} else {
childMainPosition += childMainAxisExtent + childBetweenSpace;
}
child = childParentData.nextSibling;
}
if (flipCrossAxis) {
crossAxisOffset -= runBetweenSpace;
} else {
crossAxisOffset += runCrossAxisExtent + runBetweenSpace;
}
runCrossAxisOffset += runCrossAxisExtent + runBetweenSpace;
}
}

View File

@ -952,18 +952,4 @@ void main() {
// the individual widths.
expect(tester.getSize(find.byType(IntrinsicWidth)).width, 5 * 16 + 60 + 3 * 16);
});
testWidgets('Wrap alignment flipped spaceInBetween', (WidgetTester tester) async {
await tester.pumpWidget(const Wrap(
textDirection: TextDirection.rtl,
alignment: WrapAlignment.spaceBetween,
children: <Widget>[
SizedBox(width: 100.0, height: 100.0),
],
));
expect(tester.renderObject<RenderBox>(find.byType(Wrap)).size, equals(const Size(800.0, 600.0)));
verify(tester, <Offset>[
const Offset(700.0, 0.0),
]);
});
}