Commit 787fb3be authored by Ian Hickson's avatar Ian Hickson Committed by Adam Barth

Simplify intrinsic dimension APIs (#4283)

parent 52cf2891
...@@ -454,38 +454,42 @@ class RenderBoxToRenderSectorAdapter extends RenderBox with RenderObjectWithChil ...@@ -454,38 +454,42 @@ class RenderBoxToRenderSectorAdapter extends RenderBox with RenderObjectWithChil
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
if (child == null) if (child == null)
return super.getMinIntrinsicWidth(constraints); return 0.0;
return getIntrinsicDimensions(constraints).width; return getIntrinsicDimensions(height: height).width;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
if (child == null) if (child == null)
return super.getMaxIntrinsicWidth(constraints); return 0.0;
return getIntrinsicDimensions(constraints).width; return getIntrinsicDimensions(height: height).width;
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
if (child == null) if (child == null)
return super.getMinIntrinsicHeight(constraints); return 0.0;
return getIntrinsicDimensions(constraints).height; return getIntrinsicDimensions(width: width).height;
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
if (child == null) if (child == null)
return super.getMaxIntrinsicHeight(constraints); return 0.0;
return getIntrinsicDimensions(constraints).height; return getIntrinsicDimensions(width: width).height;
} }
Size getIntrinsicDimensions(BoxConstraints constraints) { Size getIntrinsicDimensions({
double width: double.INFINITY,
double height: double.INFINITY
}) {
assert(child is RenderSector); assert(child is RenderSector);
assert(child.parentData is SectorParentData); assert(child.parentData is SectorParentData);
assert(constraints.maxWidth < double.INFINITY || constraints.maxHeight < double.INFINITY); assert(width != null);
double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius; assert(height != null);
double maxChildDeltaRadius = math.min(width, height) / 2.0 - innerRadius;
SectorDimensions childDimensions = child.getIntrinsicDimensions(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), innerRadius); SectorDimensions childDimensions = child.getIntrinsicDimensions(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), innerRadius);
double dimension = (innerRadius + childDimensions.deltaRadius) * 2.0; double dimension = (innerRadius + childDimensions.deltaRadius) * 2.0;
return constraints.constrain(new Size(dimension, dimension)); return constraints.constrain(new Size(dimension, dimension));
......
...@@ -14,31 +14,23 @@ class RenderSolidColorBox extends RenderDecoratedBox { ...@@ -14,31 +14,23 @@ class RenderSolidColorBox extends RenderDecoratedBox {
super(decoration: new BoxDecoration(backgroundColor: backgroundColor)); super(decoration: new BoxDecoration(backgroundColor: backgroundColor));
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
return constraints.constrainHeight( return desiredSize.width == double.INFINITY ? 0.0 : desiredSize.width;
this.desiredSize == Size.infinite ? 0.0 : desiredSize.width
);
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
return constraints.constrainWidth( return desiredSize.width == double.INFINITY ? 0.0 : desiredSize.width;
this.desiredSize == Size.infinite ? 0.0 : desiredSize.width
);
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
return constraints.constrainHeight( return desiredSize.height == double.INFINITY ? 0.0 : desiredSize.height;
this.desiredSize == Size.infinite ? 0.0 : desiredSize.height
);
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
return constraints.constrainHeight( return desiredSize.height == double.INFINITY ? 0.0 : desiredSize.height;
this.desiredSize == Size.infinite ? 0.0 : desiredSize.height
);
} }
@override @override
......
...@@ -100,47 +100,40 @@ class _RenderTabBar extends RenderBox with ...@@ -100,47 +100,40 @@ class _RenderTabBar extends RenderBox with
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
BoxConstraints widthConstraints =
new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraints.maxHeight);
double maxWidth = 0.0; double maxWidth = 0.0;
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
maxWidth = math.max(maxWidth, child.getMinIntrinsicWidth(widthConstraints)); maxWidth = math.max(maxWidth, child.getMinIntrinsicWidth(height));
final _TabBarParentData childParentData = child.parentData; final _TabBarParentData childParentData = child.parentData;
child = childParentData.nextSibling; child = childParentData.nextSibling;
} }
double width = isScrollable ? maxWidth : maxWidth * childCount; return isScrollable ? maxWidth : maxWidth * childCount;
return constraints.constrainWidth(width);
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
BoxConstraints widthConstraints =
new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraints.maxHeight);
double maxWidth = 0.0; double maxWidth = 0.0;
double totalWidth = 0.0;
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
maxWidth = math.max(maxWidth, child.getMaxIntrinsicWidth(widthConstraints)); double childWidth = child.getMaxIntrinsicWidth(height);
maxWidth = math.max(maxWidth, childWidth);
totalWidth += childWidth;
final _TabBarParentData childParentData = child.parentData; final _TabBarParentData childParentData = child.parentData;
child = childParentData.nextSibling; child = childParentData.nextSibling;
} }
double width = isScrollable ? maxWidth : maxWidth * childCount; return isScrollable ? totalWidth : maxWidth * childCount;
return constraints.constrainWidth(width);
} }
double get _tabHeight => textAndIcons ? _kTextAndIconTabHeight : _kTabHeight; double get _tabHeight => textAndIcons ? _kTextAndIconTabHeight : _kTabHeight;
double get _tabBarHeight => _tabHeight + _kTabIndicatorHeight; double get _tabBarHeight => _tabHeight + _kTabIndicatorHeight;
double _getIntrinsicHeight(BoxConstraints constraints) => constraints.constrainHeight(_tabBarHeight);
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeight(constraints); double getMinIntrinsicHeight(double width) => _tabBarHeight;
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeight(constraints); double getMaxIntrinsicHeight(double width) => _tabBarHeight;
void layoutFixedWidthTabs() { void layoutFixedWidthTabs() {
double tabWidth = size.width / childCount; double tabWidth = size.width / childCount;
......
...@@ -10,8 +10,7 @@ import 'object.dart'; ...@@ -10,8 +10,7 @@ import 'object.dart';
/// Parent data for use with [RenderBlockBase]. /// Parent data for use with [RenderBlockBase].
class BlockParentData extends ContainerBoxParentDataMixin<RenderBox> { } class BlockParentData extends ContainerBoxParentDataMixin<RenderBox> { }
typedef double _ChildSizingFunction(RenderBox child, BoxConstraints constraints); typedef double _ChildSizingFunction(RenderBox child);
typedef double _Constrainer(double value);
/// Implements the block layout algorithm. /// Implements the block layout algorithm.
/// ///
...@@ -158,102 +157,65 @@ class RenderBlock extends RenderBox ...@@ -158,102 +157,65 @@ class RenderBlock extends RenderBox
description.add('mainAxis: $mainAxis'); description.add('mainAxis: $mainAxis');
} }
double _getIntrinsicCrossAxis(BoxConstraints constraints, _ChildSizingFunction childSize, _Constrainer constrainer) { double _getIntrinsicCrossAxis(_ChildSizingFunction childSize) {
double extent = 0.0; double extent = 0.0;
BoxConstraints innerConstraints;
switch (mainAxis) {
case Axis.horizontal:
innerConstraints = constraints.heightConstraints();
break;
case Axis.vertical:
innerConstraints = constraints.widthConstraints();
break;
}
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
extent = math.max(extent, childSize(child, innerConstraints)); extent = math.max(extent, childSize(child));
final BlockParentData childParentData = child.parentData; final BlockParentData childParentData = child.parentData;
child = childParentData.nextSibling; child = childParentData.nextSibling;
} }
return constrainer(extent); return extent;
} }
double _getIntrinsicMainAxis(BoxConstraints constraints, _Constrainer constrainer) { double _getIntrinsicMainAxis(_ChildSizingFunction childSize) {
double extent = 0.0; double extent = 0.0;
BoxConstraints innerConstraints = _getInnerConstraints(constraints);
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
switch (mainAxis) { extent += childSize(child);
case Axis.horizontal:
extent += child.getMaxIntrinsicWidth(innerConstraints);
break;
case Axis.vertical:
extent += child.getMinIntrinsicHeight(innerConstraints);
break;
}
final BlockParentData childParentData = child.parentData; final BlockParentData childParentData = child.parentData;
child = childParentData.nextSibling; child = childParentData.nextSibling;
} }
return constrainer(extent); return extent;
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid());
switch (mainAxis) { switch (mainAxis) {
case Axis.horizontal: case Axis.horizontal:
return _getIntrinsicMainAxis(constraints, constraints.constrainWidth); return _getIntrinsicMainAxis((RenderBox child) => child.getMinIntrinsicWidth(height));
case Axis.vertical: case Axis.vertical:
return _getIntrinsicCrossAxis( return _getIntrinsicCrossAxis((RenderBox child) => child.getMinIntrinsicWidth(height));
constraints,
(RenderBox child, BoxConstraints innerConstraints) => child.getMinIntrinsicWidth(innerConstraints),
constraints.constrainWidth
);
} }
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid());
switch (mainAxis) { switch (mainAxis) {
case Axis.horizontal: case Axis.horizontal:
return _getIntrinsicMainAxis(constraints, constraints.constrainWidth); return _getIntrinsicMainAxis((RenderBox child) => child.getMaxIntrinsicWidth(height));
case Axis.vertical: case Axis.vertical:
return _getIntrinsicCrossAxis( return _getIntrinsicCrossAxis((RenderBox child) => child.getMaxIntrinsicWidth(height));
constraints,
(RenderBox child, BoxConstraints innerConstraints) => child.getMaxIntrinsicWidth(innerConstraints),
constraints.constrainWidth
);
} }
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid());
switch (mainAxis) { switch (mainAxis) {
case Axis.horizontal: case Axis.horizontal:
return _getIntrinsicCrossAxis( return _getIntrinsicMainAxis((RenderBox child) => child.getMinIntrinsicHeight(width));
constraints,
(RenderBox child, BoxConstraints innerConstraints) => child.getMinIntrinsicHeight(innerConstraints),
constraints.constrainHeight
);
case Axis.vertical: case Axis.vertical:
return _getIntrinsicMainAxis(constraints, constraints.constrainHeight); return _getIntrinsicCrossAxis((RenderBox child) => child.getMinIntrinsicHeight(width));
} }
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid());
switch (mainAxis) { switch (mainAxis) {
case Axis.horizontal: case Axis.horizontal:
return _getIntrinsicCrossAxis( return _getIntrinsicMainAxis((RenderBox child) => child.getMaxIntrinsicHeight(width));
constraints,
(RenderBox child, BoxConstraints innerConstraints) => child.getMaxIntrinsicHeight(innerConstraints),
constraints.constrainHeight
);
case Axis.vertical: case Axis.vertical:
return _getIntrinsicMainAxis(constraints, constraints.constrainHeight); return _getIntrinsicCrossAxis((RenderBox child) => child.getMaxIntrinsicHeight(width));
} }
} }
......
This diff is collapsed.
...@@ -239,24 +239,40 @@ class RenderCustomMultiChildLayoutBox extends RenderBox ...@@ -239,24 +239,40 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
return constraints.constrain(_delegate.getSize(constraints)); return constraints.constrain(_delegate.getSize(constraints));
} }
// TODO(ianh): It's a bit dubious to be using the getSize function from the delegate to
// figure out the intrinsic dimensions. We really should either not support intrinsics,
// or we should expose intrinsic delegate callbacks and throw if they're not implemented.
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
return _getSize(constraints).width; final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
if (width.isFinite)
return width;
return 0.0;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
return _getSize(constraints).width; final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
if (width.isFinite)
return width;
return 0.0;
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
return _getSize(constraints).height; final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
if (height.isFinite)
return height;
return 0.0;
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
return _getSize(constraints).height; final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
if (height.isFinite)
return height;
return 0.0;
} }
@override @override
......
...@@ -192,27 +192,13 @@ class RenderEditableLine extends RenderBox { ...@@ -192,27 +192,13 @@ class RenderEditableLine extends RenderBox {
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); return _preferredHeight;
return constraints.constrainWidth(0.0);
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); return _preferredHeight;
return constraints.constrainWidth(0.0);
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return constraints.constrainHeight(_preferredHeight);
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return constraints.constrainHeight(_preferredHeight);
} }
@override @override
......
...@@ -54,23 +54,13 @@ class RenderErrorBox extends RenderBox { ...@@ -54,23 +54,13 @@ class RenderErrorBox extends RenderBox {
ui.Paragraph _paragraph; ui.Paragraph _paragraph;
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
return constraints.constrainWidth(0.0); return _kMaxWidth;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
return constraints.constrainWidth(_kMaxWidth); return _kMaxHeight;
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
return constraints.constrainHeight(0.0);
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
return constraints.constrainHeight(_kMaxHeight);
} }
@override @override
......
...@@ -71,7 +71,7 @@ enum CrossAxisAlignment { ...@@ -71,7 +71,7 @@ enum CrossAxisAlignment {
baseline, baseline,
} }
typedef double _ChildSizingFunction(RenderBox child, BoxConstraints constraints); typedef double _ChildSizingFunction(RenderBox child, double extent);
/// Implements the flex layout algorithm /// Implements the flex layout algorithm
/// ///
...@@ -156,25 +156,15 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -156,25 +156,15 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
child.parentData = new FlexParentData(); child.parentData = new FlexParentData();
} }
double _getIntrinsicSize({ BoxConstraints constraints, double _getIntrinsicSize({
FlexDirection sizingDirection, FlexDirection sizingDirection,
_ChildSizingFunction childSize }) { double extent, // the extent in the direction that isn't the sizing direction
assert(constraints.debugAssertIsValid()); _ChildSizingFunction childSize // a method to find the size in the sizing direction
// http://www.w3.org/TR/2015/WD-css-flexbox-1-20150514/#intrinsic-sizes }) {
if (_direction == sizingDirection) { if (_direction == sizingDirection) {
// INTRINSIC MAIN SIZE // INTRINSIC MAIN SIZE
// Intrinsic main size is the smallest size the flex container can take // Intrinsic main size is the smallest size the flex container can take
// while maintaining the min/max-content contributions of its flex items. // while maintaining the min/max-content contributions of its flex items.
BoxConstraints childConstraints;
switch(_direction) {
case FlexDirection.horizontal:
childConstraints = new BoxConstraints(maxHeight: constraints.maxHeight);
break;
case FlexDirection.vertical:
childConstraints = new BoxConstraints(maxWidth: constraints.maxWidth);
break;
}
double totalFlex = 0.0; double totalFlex = 0.0;
double inflexibleSpace = 0.0; double inflexibleSpace = 0.0;
double maxFlexFractionSoFar = 0.0; double maxFlexFractionSoFar = 0.0;
...@@ -183,47 +173,24 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -183,47 +173,24 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
int flex = _getFlex(child); int flex = _getFlex(child);
totalFlex += flex; totalFlex += flex;
if (flex > 0) { if (flex > 0) {
double flexFraction = childSize(child, childConstraints) / _getFlex(child); double flexFraction = childSize(child, extent) / _getFlex(child);
maxFlexFractionSoFar = math.max(maxFlexFractionSoFar, flexFraction); maxFlexFractionSoFar = math.max(maxFlexFractionSoFar, flexFraction);
} else { } else {
inflexibleSpace += childSize(child, childConstraints); inflexibleSpace += childSize(child, extent);
} }
final FlexParentData childParentData = child.parentData; final FlexParentData childParentData = child.parentData;
child = childParentData.nextSibling; child = childParentData.nextSibling;
} }
double mainSize = maxFlexFractionSoFar * totalFlex + inflexibleSpace; return maxFlexFractionSoFar * totalFlex + inflexibleSpace;
// Ensure that we don't violate the given constraints with our result
switch(_direction) {
case FlexDirection.horizontal:
return constraints.constrainWidth(mainSize);
case FlexDirection.vertical:
return constraints.constrainHeight(mainSize);
}
} else { } else {
// INTRINSIC CROSS SIZE // INTRINSIC CROSS SIZE
// The spec wants us to perform layout into the given available main-axis // Intrinsic cross size is the max of the intrinsic cross sizes of the
// space and return the cross size. That's too expensive, so instead we // children, after the flexible children are fit into the available space,
// size inflexible children according to their max intrinsic size in the // with the children sized using their max intrinsic dimensions.
// main direction and use those constraints to determine their max // TODO(ianh): Support baseline alignment.
// intrinsic size in the cross direction. We don't care if the caller
// asked for max or min -- the answer is always computed using the
// max size in the main direction.
double availableMainSpace;
BoxConstraints childConstraints;
switch(_direction) {
case FlexDirection.horizontal:
childConstraints = new BoxConstraints(maxHeight: constraints.maxHeight);
availableMainSpace = constraints.maxWidth;
break;
case FlexDirection.vertical:
childConstraints = new BoxConstraints(maxWidth: constraints.maxWidth);
availableMainSpace = constraints.maxHeight;
break;
}
// Get inflexible space using the max in the main direction // Get inflexible space using the max intrinsic dimensions of fixed children in the main direction.
double availableMainSpace = extent;
int totalFlex = 0; int totalFlex = 0;
double inflexibleSpace = 0.0; double inflexibleSpace = 0.0;
double maxCrossSize = 0.0; double maxCrossSize = 0.0;
...@@ -236,16 +203,12 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -236,16 +203,12 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
if (flex == 0) { if (flex == 0) {
switch (_direction) { switch (_direction) {
case FlexDirection.horizontal: case FlexDirection.horizontal:
mainSize = child.getMaxIntrinsicWidth(childConstraints); mainSize = child.getMaxIntrinsicWidth(double.INFINITY);
BoxConstraints widthConstraints = crossSize = childSize(child, mainSize);
new BoxConstraints(minWidth: mainSize, maxWidth: mainSize);
crossSize = child.getMaxIntrinsicHeight(widthConstraints);
break; break;
case FlexDirection.vertical: case FlexDirection.vertical:
mainSize = child.getMaxIntrinsicHeight(childConstraints); mainSize = child.getMaxIntrinsicHeight(double.INFINITY);
BoxConstraints heightConstraints = crossSize = childSize(child, mainSize);
new BoxConstraints(minWidth: mainSize, maxWidth: mainSize);
crossSize = child.getMaxIntrinsicWidth(heightConstraints);
break; break;
} }
inflexibleSpace += mainSize; inflexibleSpace += mainSize;
...@@ -255,79 +218,59 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -255,79 +218,59 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
child = childParentData.nextSibling; child = childParentData.nextSibling;
} }
// Determine the spacePerFlex by allocating the remaining available space // Determine the spacePerFlex by allocating the remaining available space.
// When you're overconstrained spacePerFlex can be negative. // When you're overconstrained spacePerFlex can be negative.
double spacePerFlex = math.max(0.0, double spacePerFlex = math.max(0.0,
(availableMainSpace - inflexibleSpace) / totalFlex); (availableMainSpace - inflexibleSpace) / totalFlex);
// Size remaining items, find the maximum cross size // Size remaining (flexible) items, find the maximum cross size.
child = firstChild; child = firstChild;
while (child != null) { while (child != null) {
int flex = _getFlex(child); int flex = _getFlex(child);
if (flex > 0) { if (flex > 0)
double childMainSize = spacePerFlex * flex; maxCrossSize = math.max(maxCrossSize, childSize(child, spacePerFlex * flex));
double crossSize;
switch (_direction) {
case FlexDirection.horizontal:
BoxConstraints childConstraints =
new BoxConstraints(minWidth: childMainSize, maxWidth: childMainSize);
crossSize = child.getMaxIntrinsicHeight(childConstraints);
break;
case FlexDirection.vertical:
BoxConstraints childConstraints =
new BoxConstraints(minHeight: childMainSize, maxHeight: childMainSize);
crossSize = child.getMaxIntrinsicWidth(childConstraints);
break;
}
maxCrossSize = math.max(maxCrossSize, crossSize);
}
final FlexParentData childParentData = child.parentData; final FlexParentData childParentData = child.parentData;
child = childParentData.nextSibling; child = childParentData.nextSibling;
} }
// Ensure that we don't violate the given constraints with our result return maxCrossSize;
switch(_direction) {
case FlexDirection.horizontal:
return constraints.constrainHeight(maxCrossSize);
case FlexDirection.vertical:
return constraints.constrainWidth(maxCrossSize);
}
} }
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
return _getIntrinsicSize( return _getIntrinsicSize(
constraints: constraints,
sizingDirection: FlexDirection.horizontal, sizingDirection: FlexDirection.horizontal,
childSize: (RenderBox child, BoxConstraints innerConstraints) => child.getMinIntrinsicWidth(innerConstraints) extent: height,
childSize: (RenderBox child, double extent) => child.getMinIntrinsicWidth(extent)
); );
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
return _getIntrinsicSize( return _getIntrinsicSize(
constraints: constraints,
sizingDirection: FlexDirection.horizontal, sizingDirection: FlexDirection.horizontal,
childSize: (RenderBox child, BoxConstraints innerConstraints) => child.getMaxIntrinsicWidth(innerConstraints) extent: height,
childSize: (RenderBox child, double extent) => child.getMaxIntrinsicWidth(extent)
); );
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
return _getIntrinsicSize( return _getIntrinsicSize(
constraints: constraints,
sizingDirection: FlexDirection.vertical, sizingDirection: FlexDirection.vertical,
childSize: (RenderBox child, BoxConstraints innerConstraints) => child.getMinIntrinsicHeight(innerConstraints) extent: width,
childSize: (RenderBox child, double extent) => child.getMinIntrinsicHeight(extent)
); );
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
return _getIntrinsicSize( return _getIntrinsicSize(
constraints: constraints,
sizingDirection: FlexDirection.vertical, sizingDirection: FlexDirection.vertical,
childSize: (RenderBox child, BoxConstraints innerConstraints) => child.getMaxIntrinsicHeight(innerConstraints)); extent: width,
childSize: (RenderBox child, double extent) => child.getMaxIntrinsicHeight(extent)
);
} }
@override @override
...@@ -352,8 +295,6 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl ...@@ -352,8 +295,6 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
@override @override
void performLayout() { void performLayout() {
// Originally based on http://www.w3.org/TR/css-flexbox-1/ Section 9.7 Resolving Flexible Lengths
// Determine used flex factor, size inflexible items, calculate free space. // Determine used flex factor, size inflexible items, calculate free space.
int totalFlex = 0; int totalFlex = 0;
int totalChildren = 0; int totalChildren = 0;
......
...@@ -240,24 +240,40 @@ class RenderFlow extends RenderBox ...@@ -240,24 +240,40 @@ class RenderFlow extends RenderBox
@override @override
bool get isRepaintBoundary => true; bool get isRepaintBoundary => true;
// TODO(ianh): It's a bit dubious to be using the getSize function from the delegate to
// figure out the intrinsic dimensions. We really should either not support intrinsics,
// or we should expose intrinsic delegate callbacks and throw if they're not implemented.
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
return _getSize(constraints).width; final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
if (width.isFinite)
return width;
return 0.0;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
return _getSize(constraints).width; final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
if (width.isFinite)
return width;
return 0.0;
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
return _getSize(constraints).height; final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
if (height.isFinite)
return height;
return 0.0;
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
return _getSize(constraints).height; final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
if (height.isFinite)
return height;
return 0.0;
} }
@override @override
......
...@@ -181,26 +181,34 @@ abstract class GridDelegate { ...@@ -181,26 +181,34 @@ abstract class GridDelegate {
/// Returns the minimum width that this grid could be without failing to paint /// Returns the minimum width that this grid could be without failing to paint
/// its contents within itself. /// its contents within itself.
double getMinIntrinsicWidth(BoxConstraints constraints, int childCount) { ///
return constraints.constrainWidth(_getGridSize(constraints, childCount).width); /// For more details, see [RenderBox.getMinIntrinsicWidth].
double getMinIntrinsicWidth(double height, int childCount) {
return _getGridSize(new BoxConstraints.tightForFinite(height: height), childCount).width;
} }
/// Returns the smallest width beyond which increasing the width never /// Returns the smallest width beyond which increasing the width never
/// decreases the preferred height. /// decreases the preferred height.
double getMaxIntrinsicWidth(BoxConstraints constraints, int childCount) { ///
return constraints.constrainWidth(_getGridSize(constraints, childCount).width); /// For more details, see [RenderBox.getMaxIntrinsicWidth].
double getMaxIntrinsicWidth(double height, int childCount) {
return _getGridSize(new BoxConstraints.tightForFinite(height: height), childCount).width;
} }
/// Return the minimum height that this grid could be without failing to paint /// Return the minimum height that this grid could be without failing to paint
/// its contents within itself. /// its contents within itself.
double getMinIntrinsicHeight(BoxConstraints constraints, int childCount) { ///
return constraints.constrainHeight(_getGridSize(constraints, childCount).height); /// For more details, see [RenderBox.getMinIntrinsicHeight].
double getMinIntrinsicHeight(double width, int childCount) {
return _getGridSize(new BoxConstraints.tightForFinite(width: width), childCount).height;
} }
/// Returns the smallest height beyond which increasing the height never /// Returns the smallest height beyond which increasing the height never
/// decreases the preferred width. /// decreases the preferred width.
double getMaxIntrinsicHeight(BoxConstraints constraints, int childCount) { ///
return constraints.constrainHeight(_getGridSize(constraints, childCount).height); /// For more details, see [RenderBox.getMaxIntrinsicHeight].
double getMaxIntrinsicHeight(double width, int childCount) {
return _getGridSize(new BoxConstraints.tightForFinite(width: width), childCount).height;
} }
} }
...@@ -293,13 +301,13 @@ class FixedColumnCountGridDelegate extends GridDelegateWithInOrderChildPlacement ...@@ -293,13 +301,13 @@ class FixedColumnCountGridDelegate extends GridDelegateWithInOrderChildPlacement
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints, int childCount) { double getMinIntrinsicWidth(double height, int childCount) {
return constraints.constrainWidth(0.0); return 0.0;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints, int childCount) { double getMaxIntrinsicWidth(double height, int childCount) {
return constraints.constrainWidth(0.0); return 0.0;
} }
} }
...@@ -359,13 +367,13 @@ class MaxTileWidthGridDelegate extends GridDelegateWithInOrderChildPlacement { ...@@ -359,13 +367,13 @@ class MaxTileWidthGridDelegate extends GridDelegateWithInOrderChildPlacement {
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints, int childCount) { double getMinIntrinsicWidth(double height, int childCount) {
return constraints.constrainWidth(0.0); return 0.0;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints, int childCount) { double getMaxIntrinsicWidth(double height, int childCount) {
return constraints.constrainWidth(maxTileWidth * childCount); return maxTileWidth * childCount;
} }
} }
...@@ -470,27 +478,23 @@ class RenderGrid extends RenderVirtualViewport<GridParentData> { ...@@ -470,27 +478,23 @@ class RenderGrid extends RenderVirtualViewport<GridParentData> {
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid()); return _delegate.getMinIntrinsicWidth(height, virtualChildCount);
return _delegate.getMinIntrinsicWidth(constraints, virtualChildCount);
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid()); return _delegate.getMaxIntrinsicWidth(height, virtualChildCount);
return _delegate.getMaxIntrinsicWidth(constraints, virtualChildCount);
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); return _delegate.getMinIntrinsicHeight(width, virtualChildCount);
return _delegate.getMinIntrinsicHeight(constraints, virtualChildCount);
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); return _delegate.getMaxIntrinsicHeight(width, virtualChildCount);
return _delegate.getMaxIntrinsicHeight(constraints, virtualChildCount);
} }
@override @override
......
...@@ -205,31 +205,27 @@ class RenderImage extends RenderBox { ...@@ -205,31 +205,27 @@ class RenderImage extends RenderBox {
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid());
if (_width == null && _height == null) if (_width == null && _height == null)
return constraints.constrainWidth(0.0); return 0.0;
return _sizeForConstraints(constraints).width; return _sizeForConstraints(new BoxConstraints.tightForFinite(height: height)).width;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid()); return _sizeForConstraints(new BoxConstraints.tightForFinite(height: height)).width;
return _sizeForConstraints(constraints).width;
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid());
if (_width == null && _height == null) if (_width == null && _height == null)
return constraints.constrainHeight(0.0); return 0.0;
return _sizeForConstraints(constraints).height; return _sizeForConstraints(new BoxConstraints.tightForFinite(width: width)).height;
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); return _sizeForConstraints(new BoxConstraints.tightForFinite(width: width)).height;
return _sizeForConstraints(constraints).height;
} }
@override @override
......
...@@ -87,7 +87,7 @@ class RenderList extends RenderVirtualViewport<ListParentData> { ...@@ -87,7 +87,7 @@ class RenderList extends RenderVirtualViewport<ListParentData> {
double get _preferredExtent { double get _preferredExtent {
if (itemExtent == null) if (itemExtent == null)
return double.INFINITY; return double.INFINITY;
int count = virtualChildCount; final int count = virtualChildCount;
if (count == null) if (count == null)
return double.INFINITY; return double.INFINITY;
double extent = itemExtent * count; double extent = itemExtent * count;
...@@ -96,44 +96,52 @@ class RenderList extends RenderVirtualViewport<ListParentData> { ...@@ -96,44 +96,52 @@ class RenderList extends RenderVirtualViewport<ListParentData> {
return extent; return extent;
} }
double _getIntrinsicWidth(BoxConstraints constraints) { double _getIntrinsicWidth() {
assert(constraints.debugAssertIsValid());
switch (mainAxis) { switch (mainAxis) {
case Axis.vertical: case Axis.vertical:
return constraints.constrainWidth(0.0); assert(debugThrowIfNotCheckingIntrinsics());
return 0.0;
case Axis.horizontal: case Axis.horizontal:
return constraints.constrainWidth(_preferredExtent); final double width = _preferredExtent;
if (width.isFinite)
return width;
assert(debugThrowIfNotCheckingIntrinsics());
return 0.0;
} }
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
return _getIntrinsicWidth(constraints); return _getIntrinsicWidth();
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
return _getIntrinsicWidth(constraints); return _getIntrinsicWidth();
} }
double _getIntrinsicHeight(BoxConstraints constraints) { double _getIntrinsicHeight() {
assert(constraints.debugAssertIsValid());
switch (mainAxis) { switch (mainAxis) {
case Axis.vertical: case Axis.vertical:
return constraints.constrainHeight(_preferredExtent); final double height = _preferredExtent;
if (height.isFinite)
return height;
assert(debugThrowIfNotCheckingIntrinsics());
return 0.0;
case Axis.horizontal: case Axis.horizontal:
return constraints.constrainHeight(0.0); assert(debugThrowIfNotCheckingIntrinsics());
return 0.0;
} }
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
return _getIntrinsicHeight(constraints); return _getIntrinsicHeight();
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
return _getIntrinsicHeight(constraints); return _getIntrinsicHeight();
} }
@override @override
......
...@@ -14,18 +14,6 @@ class RenderOffStage extends RenderBox with RenderObjectWithChildMixin<RenderBox ...@@ -14,18 +14,6 @@ class RenderOffStage extends RenderBox with RenderObjectWithChildMixin<RenderBox
this.child = child; this.child = child;
} }
@override
double getMinIntrinsicWidth(BoxConstraints constraints) => constraints.minWidth;
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) => constraints.minWidth;
@override
double getMinIntrinsicHeight(BoxConstraints constraints) => constraints.minHeight;
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) => constraints.minHeight;
@override @override
bool get sizedByParent => true; bool get sizedByParent => true;
......
...@@ -87,45 +87,43 @@ class RenderParagraph extends RenderBox { ...@@ -87,45 +87,43 @@ class RenderParagraph extends RenderBox {
markNeedsPaint(); markNeedsPaint();
} }
void _layoutText(BoxConstraints constraints) { void _layoutText({ double minWidth: 0.0, double maxWidth: double.INFINITY }) {
assert(constraints != null); _textPainter.layout(minWidth: minWidth, maxWidth: _softWrap ? maxWidth : double.INFINITY);
assert(constraints.debugAssertIsValid());
_textPainter.layout(minWidth: constraints.minWidth, maxWidth: _softWrap ? constraints.maxWidth : double.INFINITY);
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
_layoutText(constraints); _layoutText();
return constraints.constrainWidth(_textPainter.minIntrinsicWidth); return _textPainter.minIntrinsicWidth;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
_layoutText(constraints); _layoutText();
return constraints.constrainWidth(_textPainter.maxIntrinsicWidth); return _textPainter.maxIntrinsicWidth;
} }
double _getIntrinsicHeight(BoxConstraints constraints) { double _getIntrinsicHeight(double width) {
_layoutText(constraints); _layoutText(minWidth: width, maxWidth: width);
return constraints.constrainHeight(_textPainter.height); return _textPainter.height;
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); return _getIntrinsicHeight(width);
return _getIntrinsicHeight(constraints);
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); return _getIntrinsicHeight(width);
return _getIntrinsicHeight(constraints);
} }
@override @override
double computeDistanceToActualBaseline(TextBaseline baseline) { double computeDistanceToActualBaseline(TextBaseline baseline) {
assert(!needsLayout); assert(!needsLayout);
_layoutText(constraints); assert(constraints != null);
assert(constraints.debugAssertIsValid());
_layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
return _textPainter.computeDistanceToActualBaseline(baseline); return _textPainter.computeDistanceToActualBaseline(baseline);
} }
...@@ -136,7 +134,7 @@ class RenderParagraph extends RenderBox { ...@@ -136,7 +134,7 @@ class RenderParagraph extends RenderBox {
void handleEvent(PointerEvent event, BoxHitTestEntry entry) { void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
if (event is! PointerDownEvent) if (event is! PointerDownEvent)
return; return;
_layoutText(constraints); _layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
Offset offset = entry.localPosition.toOffset(); Offset offset = entry.localPosition.toOffset();
TextPosition position = _textPainter.getPositionForOffset(offset); TextPosition position = _textPainter.getPositionForOffset(offset);
TextSpan span = _textPainter.text.getSpanForPosition(position); TextSpan span = _textPainter.text.getSpanForPosition(position);
...@@ -149,7 +147,7 @@ class RenderParagraph extends RenderBox { ...@@ -149,7 +147,7 @@ class RenderParagraph extends RenderBox {
@override @override
void performLayout() { void performLayout() {
_layoutText(constraints); _layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
size = constraints.constrain(_textPainter.size); size = constraints.constrain(_textPainter.size);
final bool didOverflowWidth = size.width < _textPainter.width; final bool didOverflowWidth = size.width < _textPainter.width;
...@@ -200,7 +198,7 @@ class RenderParagraph extends RenderBox { ...@@ -200,7 +198,7 @@ class RenderParagraph extends RenderBox {
// //
// If you remove this call, make sure that changing the textAlign still // If you remove this call, make sure that changing the textAlign still
// works properly. // works properly.
_layoutText(constraints); _layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
final Canvas canvas = context.canvas; final Canvas canvas = context.canvas;
if (_hasVisualOverflow) { if (_hasVisualOverflow) {
final Rect bounds = offset & size; final Rect bounds = offset & size;
......
...@@ -97,13 +97,13 @@ class RenderPerformanceOverlay extends RenderBox { ...@@ -97,13 +97,13 @@ class RenderPerformanceOverlay extends RenderBox {
bool get alwaysNeedsCompositing => true; bool get alwaysNeedsCompositing => true;
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
return constraints.constrainWidth(0.0); return 0.0;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
return constraints.constrainWidth(0.0); return 0.0;
} }
double get _intrinsicHeight { double get _intrinsicHeight {
...@@ -119,13 +119,13 @@ class RenderPerformanceOverlay extends RenderBox { ...@@ -119,13 +119,13 @@ class RenderPerformanceOverlay extends RenderBox {
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
return constraints.constrainHeight(_intrinsicHeight); return _intrinsicHeight;
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
return constraints.constrainHeight(_intrinsicHeight); return _intrinsicHeight;
} }
@override @override
......
...@@ -43,35 +43,31 @@ class RenderRotatedBox extends RenderBox with RenderObjectWithChildMixin<RenderB ...@@ -43,35 +43,31 @@ class RenderRotatedBox extends RenderBox with RenderObjectWithChildMixin<RenderB
bool get _isVertical => quarterTurns % 2 == 1; bool get _isVertical => quarterTurns % 2 == 1;
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid()); if (child == null)
if (child != null) return 0.0;
return _isVertical ? child.getMinIntrinsicHeight(constraints.flipped) : child.getMinIntrinsicWidth(constraints); return _isVertical ? child.getMinIntrinsicHeight(height) : child.getMinIntrinsicWidth(height);
return super.getMinIntrinsicWidth(constraints);
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid()); if (child == null)
if (child != null) return 0.0;
return _isVertical ? child.getMaxIntrinsicHeight(constraints.flipped) : child.getMaxIntrinsicWidth(constraints); return _isVertical ? child.getMaxIntrinsicHeight(height) : child.getMaxIntrinsicWidth(height);
return super.getMaxIntrinsicWidth(constraints);
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); if (child == null)
if (child != null) return 0.0;
return _isVertical ? child.getMinIntrinsicWidth(constraints.flipped) : child.getMinIntrinsicHeight(constraints); return _isVertical ? child.getMinIntrinsicWidth(width) : child.getMinIntrinsicHeight(width);
return super.getMinIntrinsicHeight(constraints);
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); if (child == null)
if (child != null) return 0.0;
return _isVertical ? child.getMaxIntrinsicWidth(constraints.flipped) : child.getMaxIntrinsicHeight(constraints); return _isVertical ? child.getMaxIntrinsicWidth(width) : child.getMaxIntrinsicHeight(width);
return super.getMaxIntrinsicHeight(constraints);
} }
Matrix4 _paintTransform; Matrix4 _paintTransform;
......
...@@ -224,78 +224,37 @@ abstract class RenderStackBase extends RenderBox ...@@ -224,78 +224,37 @@ abstract class RenderStackBase extends RenderBox
} }
} }
@override double _getIntrinsicDimension(double mainChildSizeGetter(RenderBox child)) {
double getMinIntrinsicWidth(BoxConstraints constraints) { double extent = 0.0;
assert(constraints.debugAssertIsValid());
double width = constraints.minWidth;
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
final StackParentData childParentData = child.parentData; final StackParentData childParentData = child.parentData;
if (!childParentData.isPositioned) if (!childParentData.isPositioned)
width = math.max(width, child.getMinIntrinsicWidth(constraints)); extent = math.max(extent, mainChildSizeGetter(child));
assert(child.parentData == childParentData); assert(child.parentData == childParentData);
child = childParentData.nextSibling; child = childParentData.nextSibling;
} }
assert(width == constraints.constrainWidth(width)); return extent;
return width;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid()); return _getIntrinsicDimension((RenderBox child) => child.getMinIntrinsicWidth(height));
bool hasNonPositionedChildren = false;
double width = constraints.minWidth;
RenderBox child = firstChild;
while (child != null) {
final StackParentData childParentData = child.parentData;
if (!childParentData.isPositioned) {
hasNonPositionedChildren = true;
width = math.max(width, child.getMaxIntrinsicWidth(constraints));
}
assert(child.parentData == childParentData);
child = childParentData.nextSibling;
}
if (!hasNonPositionedChildren)
return constraints.constrainWidth();
assert(width == constraints.constrainWidth(width));
return width;
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid()); return _getIntrinsicDimension((RenderBox child) => child.getMaxIntrinsicWidth(height));
double height = constraints.minHeight;
RenderBox child = firstChild;
while (child != null) {
final StackParentData childParentData = child.parentData;
if (!childParentData.isPositioned)
height = math.max(height, child.getMinIntrinsicHeight(constraints));
assert(child.parentData == childParentData);
child = childParentData.nextSibling;
}
assert(height == constraints.constrainHeight(height));
return height;
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); return _getIntrinsicDimension((RenderBox child) => child.getMinIntrinsicHeight(width));
bool hasNonPositionedChildren = false; }
double height = constraints.minHeight;
RenderBox child = firstChild; @override
while (child != null) { double getMaxIntrinsicHeight(double width) {
final StackParentData childParentData = child.parentData; return _getIntrinsicDimension((RenderBox child) => child.getMaxIntrinsicHeight(width));
if (!childParentData.isPositioned) {
hasNonPositionedChildren = true;
height = math.max(height, child.getMaxIntrinsicHeight(constraints));
}
assert(child.parentData == childParentData);
child = childParentData.nextSibling;
}
if (!hasNonPositionedChildren)
return constraints.constrainHeight();
assert(height == constraints.constrainHeight(height));
return height;
} }
@override @override
......
...@@ -82,7 +82,7 @@ class IntrinsicColumnWidth extends TableColumnWidth { ...@@ -82,7 +82,7 @@ class IntrinsicColumnWidth extends TableColumnWidth {
double minIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) { double minIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
double result = 0.0; double result = 0.0;
for (RenderBox cell in cells) for (RenderBox cell in cells)
result = math.max(result, cell.getMinIntrinsicWidth(const BoxConstraints())); result = math.max(result, cell.getMinIntrinsicWidth(double.INFINITY));
return result; return result;
} }
...@@ -90,7 +90,7 @@ class IntrinsicColumnWidth extends TableColumnWidth { ...@@ -90,7 +90,7 @@ class IntrinsicColumnWidth extends TableColumnWidth {
double maxIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) { double maxIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
double result = 0.0; double result = 0.0;
for (RenderBox cell in cells) for (RenderBox cell in cells)
result = math.max(result, cell.getMaxIntrinsicWidth(const BoxConstraints())); result = math.max(result, cell.getMaxIntrinsicWidth(double.INFINITY));
return result; return result;
} }
...@@ -689,36 +689,33 @@ class RenderTable extends RenderBox { ...@@ -689,36 +689,33 @@ class RenderTable extends RenderBox {
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid());
assert(_children.length == rows * columns); assert(_children.length == rows * columns);
double totalMinWidth = 0.0; double totalMinWidth = 0.0;
for (int x = 0; x < columns; x += 1) { for (int x = 0; x < columns; x += 1) {
TableColumnWidth columnWidth = _columnWidths[x] ?? defaultColumnWidth; TableColumnWidth columnWidth = _columnWidths[x] ?? defaultColumnWidth;
Iterable<RenderBox> columnCells = column(x); Iterable<RenderBox> columnCells = column(x);
totalMinWidth += columnWidth.minIntrinsicWidth(columnCells, constraints.maxWidth); totalMinWidth += columnWidth.minIntrinsicWidth(columnCells, double.INFINITY);
} }
return constraints.constrainWidth(totalMinWidth); return totalMinWidth;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid());
assert(_children.length == rows * columns); assert(_children.length == rows * columns);
double totalMaxWidth = 0.0; double totalMaxWidth = 0.0;
for (int x = 0; x < columns; x += 1) { for (int x = 0; x < columns; x += 1) {
TableColumnWidth columnWidth = _columnWidths[x] ?? defaultColumnWidth; TableColumnWidth columnWidth = _columnWidths[x] ?? defaultColumnWidth;
Iterable<RenderBox> columnCells = column(x); Iterable<RenderBox> columnCells = column(x);
totalMaxWidth += columnWidth.maxIntrinsicWidth(columnCells, constraints.maxWidth); totalMaxWidth += columnWidth.maxIntrinsicWidth(columnCells, double.INFINITY);
} }
return constraints.constrainWidth(totalMaxWidth); return totalMaxWidth;
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
// winner of the 2016 world's most expensive intrinsic dimension function award // winner of the 2016 world's most expensive intrinsic dimension function award
// honorable mention, most likely to improve if taught about memoization award // honorable mention, most likely to improve if taught about memoization award
assert(constraints.debugAssertIsValid());
assert(_children.length == rows * columns); assert(_children.length == rows * columns);
final List<double> widths = _computeColumnWidths(constraints); final List<double> widths = _computeColumnWidths(constraints);
double rowTop = 0.0; double rowTop = 0.0;
...@@ -728,16 +725,16 @@ class RenderTable extends RenderBox { ...@@ -728,16 +725,16 @@ class RenderTable extends RenderBox {
final int xy = x + y * columns; final int xy = x + y * columns;
RenderBox child = _children[xy]; RenderBox child = _children[xy];
if (child != null) if (child != null)
rowHeight = math.max(rowHeight, child.getMaxIntrinsicHeight(new BoxConstraints.tightFor(width: widths[x]))); rowHeight = math.max(rowHeight, child.getMaxIntrinsicHeight(widths[x]));
} }
rowTop += rowHeight; rowTop += rowHeight;
} }
return constraints.constrainHeight(rowTop); return rowTop;
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
return getMinIntrinsicHeight(constraints); return getMinIntrinsicHeight(width);
} }
double _baselineDistance; double _baselineDistance;
......
...@@ -218,35 +218,31 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin< ...@@ -218,35 +218,31 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
} }
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid());
if (child != null) if (child != null)
return constraints.constrainWidth(child.getMinIntrinsicWidth(_getInnerConstraints(constraints))); return child.getMinIntrinsicWidth(height);
return super.getMinIntrinsicWidth(constraints); return 0.0;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid());
if (child != null) if (child != null)
return constraints.constrainWidth(child.getMaxIntrinsicWidth(_getInnerConstraints(constraints))); return child.getMaxIntrinsicWidth(height);
return super.getMaxIntrinsicWidth(constraints); return 0.0;
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid());
if (child != null) if (child != null)
return constraints.constrainHeight(child.getMinIntrinsicHeight(_getInnerConstraints(constraints))); return child.getMinIntrinsicHeight(width);
return super.getMinIntrinsicHeight(constraints); return 0.0;
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid());
if (child != null) if (child != null)
return constraints.constrainHeight(child.getMaxIntrinsicHeight(_getInnerConstraints(constraints))); return child.getMaxIntrinsicHeight(width);
return super.getMaxIntrinsicHeight(constraints); return 0.0;
} }
// We don't override computeDistanceToActualBaseline(), because we // We don't override computeDistanceToActualBaseline(), because we
...@@ -353,6 +349,51 @@ abstract class RenderVirtualViewport<T extends ContainerBoxParentDataMixin<Rende ...@@ -353,6 +349,51 @@ abstract class RenderVirtualViewport<T extends ContainerBoxParentDataMixin<Rende
markNeedsLayout(); markNeedsLayout();
} }
/// Throws an exception if asserts are enabled, unless the
/// [RenderObject.debugCheckingIntrinsics] flag is set.
///
/// This is a convenience function for subclasses to call from their
/// intrinsic-sizing functions if they don't have a good way to generate the
/// numbers.
bool debugThrowIfNotCheckingIntrinsics() {
assert(() {
if (!RenderObject.debugCheckingIntrinsics) {
throw new FlutterError(
'RenderVirtualViewport does not support returning intrinsic dimensions.\n'
'Calculating the intrinsic dimensions would require walking the entire '
'child list, which cannot reliably and efficiently be done for render '
'objects that potentially generate their child list during layout.'
);
}
return true;
});
return true;
}
@override
double getMinIntrinsicWidth(double height) {
assert(debugThrowIfNotCheckingIntrinsics);
return 0.0;
}
@override
double getMaxIntrinsicWidth(double height) {
assert(debugThrowIfNotCheckingIntrinsics);
return 0.0;
}
@override
double getMinIntrinsicHeight(double width) {
assert(debugThrowIfNotCheckingIntrinsics);
return 0.0;
}
@override
double getMaxIntrinsicHeight(double width) {
assert(debugThrowIfNotCheckingIntrinsics);
return 0.0;
}
@override @override
bool hitTestChildren(HitTestResult result, { Point position }) { bool hitTestChildren(HitTestResult result, { Point position }) {
return defaultHitTestChildren(result, position: position + -_effectivePaintOffset); return defaultHitTestChildren(result, position: position + -_effectivePaintOffset);
......
...@@ -44,32 +44,42 @@ class _RenderLayoutBuilder extends RenderBox with RenderObjectWithChildMixin<Ren ...@@ -44,32 +44,42 @@ class _RenderLayoutBuilder extends RenderBox with RenderObjectWithChildMixin<Ren
markNeedsLayout(); markNeedsLayout();
} }
double getIntrinsicWidth(BoxConstraints constraints) => constraints.constrainWidth(); bool _debugThrowIfNotCheckingIntrinsics() {
assert(() {
double getIntrinsicHeight(BoxConstraints constraints) => constraints.constrainHeight(); if (!RenderObject.debugCheckingIntrinsics) {
throw new FlutterError(
'LayoutBuilder does not support returning intrinsic dimensions.\n'
'Calculating the intrinsic dimensions would require running the layout callback speculatively, '
'which might mutate the live render object tree.'
);
}
return true;
});
return true;
}
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid()); assert(_debugThrowIfNotCheckingIntrinsics());
return getIntrinsicWidth(constraints); return 0.0;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid()); assert(_debugThrowIfNotCheckingIntrinsics());
return getIntrinsicWidth(constraints); return 0.0;
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); assert(_debugThrowIfNotCheckingIntrinsics());
return getIntrinsicHeight(constraints); return 0.0;
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); assert(_debugThrowIfNotCheckingIntrinsics());
return getIntrinsicHeight(constraints); return 0.0;
} }
@override @override
...@@ -85,7 +95,7 @@ class _RenderLayoutBuilder extends RenderBox with RenderObjectWithChildMixin<Ren ...@@ -85,7 +95,7 @@ class _RenderLayoutBuilder extends RenderBox with RenderObjectWithChildMixin<Ren
if (callback != null) if (callback != null)
invokeLayoutCallback(callback); invokeLayoutCallback(callback);
if (child != null) if (child != null)
child.layout(constraints.loosen(), parentUsesSize: false); child.layout(constraints.loosen());
} }
@override @override
......
...@@ -368,48 +368,28 @@ class _RenderLazyBlock extends RenderVirtualViewport<_LazyBlockParentData> { ...@@ -368,48 +368,28 @@ class _RenderLazyBlock extends RenderVirtualViewport<_LazyBlockParentData> {
return true; return true;
} }
double getIntrinsicWidth(BoxConstraints constraints) {
switch (mainAxis) {
case Axis.horizontal:
return constraints.constrainWidth(0.0);
case Axis.vertical:
assert(_debugThrowIfNotCheckingIntrinsics());
return constraints.constrainWidth(0.0);
}
}
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid()); assert(_debugThrowIfNotCheckingIntrinsics());
return getIntrinsicWidth(constraints); return 0.0;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
assert(constraints.debugAssertIsValid()); assert(_debugThrowIfNotCheckingIntrinsics());
return getIntrinsicWidth(constraints); return 0.0;
}
double getIntrinsicHeight(BoxConstraints constraints) {
switch (mainAxis) {
case Axis.horizontal:
return constraints.constrainHeight(0.0);
case Axis.vertical:
assert(_debugThrowIfNotCheckingIntrinsics());
return constraints.constrainHeight(0.0);
}
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); assert(_debugThrowIfNotCheckingIntrinsics());
return getIntrinsicHeight(constraints); return 0.0;
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
assert(constraints.debugAssertIsValid()); assert(_debugThrowIfNotCheckingIntrinsics());
return getIntrinsicHeight(constraints); return 0.0;
} }
@override @override
......
...@@ -4,21 +4,96 @@ ...@@ -4,21 +4,96 @@
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'rendering_tester.dart';
void main() { void main() {
test('Intrinsic sizing', () { test('Intrinsic sizing 2.0', () {
RenderAspectRatio box = new RenderAspectRatio(aspectRatio: 2.0); RenderAspectRatio box = new RenderAspectRatio(aspectRatio: 2.0);
BoxConstraints constraints = new BoxConstraints.loose(new Size(200.0, 200.0)); expect(box.getMinIntrinsicWidth(200.0), 400.0);
expect(box.getMinIntrinsicWidth(constraints), equals(0.0)); expect(box.getMinIntrinsicWidth(400.0), 800.0);
expect(box.getMaxIntrinsicWidth(constraints), equals(200.0));
expect(box.getMinIntrinsicHeight(constraints), equals(0.0)); expect(box.getMaxIntrinsicWidth(200.0), 400.0);
expect(box.getMaxIntrinsicHeight(constraints), equals(100.0)); expect(box.getMaxIntrinsicWidth(400.0), 800.0);
constraints = new BoxConstraints(maxHeight: 400.0); expect(box.getMinIntrinsicHeight(200.0), 100.0);
expect(box.getMinIntrinsicWidth(constraints), equals(0.0)); expect(box.getMinIntrinsicHeight(400.0), 200.0);
expect(box.getMaxIntrinsicWidth(constraints), equals(800.0));
expect(box.getMinIntrinsicHeight(constraints), equals(0.0)); expect(box.getMaxIntrinsicHeight(200.0), 100.0);
expect(box.getMaxIntrinsicHeight(constraints), equals(400.0)); expect(box.getMaxIntrinsicHeight(400.0), 200.0);
expect(box.getMinIntrinsicWidth(double.INFINITY), 0.0);
expect(box.getMaxIntrinsicWidth(double.INFINITY), 0.0);
expect(box.getMinIntrinsicHeight(double.INFINITY), 0.0);
expect(box.getMaxIntrinsicHeight(double.INFINITY), 0.0);
});
test('Intrinsic sizing 0.5', () {
RenderAspectRatio box = new RenderAspectRatio(aspectRatio: 0.5);
expect(box.getMinIntrinsicWidth(200.0), 100.0);
expect(box.getMinIntrinsicWidth(400.0), 200.0);
expect(box.getMaxIntrinsicWidth(200.0), 100.0);
expect(box.getMaxIntrinsicWidth(400.0), 200.0);
expect(box.getMinIntrinsicHeight(200.0), 400.0);
expect(box.getMinIntrinsicHeight(400.0), 800.0);
expect(box.getMaxIntrinsicHeight(200.0), 400.0);
expect(box.getMaxIntrinsicHeight(400.0), 800.0);
expect(box.getMinIntrinsicWidth(double.INFINITY), 0.0);
expect(box.getMaxIntrinsicWidth(double.INFINITY), 0.0);
expect(box.getMinIntrinsicHeight(double.INFINITY), 0.0);
expect(box.getMaxIntrinsicHeight(double.INFINITY), 0.0);
});
test('Intrinsic sizing 2.0', () {
RenderAspectRatio box = new RenderAspectRatio(
aspectRatio: 2.0,
child: new RenderSizedBox(const Size(90.0, 70.0))
);
expect(box.getMinIntrinsicWidth(200.0), 400.0);
expect(box.getMinIntrinsicWidth(400.0), 800.0);
expect(box.getMaxIntrinsicWidth(200.0), 400.0);
expect(box.getMaxIntrinsicWidth(400.0), 800.0);
expect(box.getMinIntrinsicHeight(200.0), 100.0);
expect(box.getMinIntrinsicHeight(400.0), 200.0);
expect(box.getMaxIntrinsicHeight(200.0), 100.0);
expect(box.getMaxIntrinsicHeight(400.0), 200.0);
expect(box.getMinIntrinsicWidth(double.INFINITY), 90.0);
expect(box.getMaxIntrinsicWidth(double.INFINITY), 90.0);
expect(box.getMinIntrinsicHeight(double.INFINITY), 70.0);
expect(box.getMaxIntrinsicHeight(double.INFINITY), 70.0);
});
test('Intrinsic sizing 0.5', () {
RenderAspectRatio box = new RenderAspectRatio(
aspectRatio: 0.5,
child: new RenderSizedBox(const Size(90.0, 70.0))
);
expect(box.getMinIntrinsicWidth(200.0), 100.0);
expect(box.getMinIntrinsicWidth(400.0), 200.0);
expect(box.getMaxIntrinsicWidth(200.0), 100.0);
expect(box.getMaxIntrinsicWidth(400.0), 200.0);
expect(box.getMinIntrinsicHeight(200.0), 400.0);
expect(box.getMinIntrinsicHeight(400.0), 800.0);
expect(box.getMaxIntrinsicHeight(200.0), 400.0);
expect(box.getMaxIntrinsicHeight(400.0), 800.0);
expect(box.getMinIntrinsicWidth(double.INFINITY), 90.0);
expect(box.getMaxIntrinsicWidth(double.INFINITY), 90.0);
expect(box.getMinIntrinsicHeight(double.INFINITY), 70.0);
expect(box.getMaxIntrinsicHeight(double.INFINITY), 70.0);
}); });
} }
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/rendering.dart';
import 'package:test/test.dart';
void main() {
test('block intrinsics', () {
RenderParagraph paragraph = new RenderParagraph(
new TextSpan(
style: new TextStyle(height: 1.0),
text: 'Hello World'
)
);
const BoxConstraints unconstrained = const BoxConstraints();
double textWidth = paragraph.getMaxIntrinsicWidth(unconstrained);
double oneLineTextHeight = paragraph.getMinIntrinsicHeight(unconstrained);
final BoxConstraints constrained = new BoxConstraints(maxWidth: textWidth * 0.9);
double wrappedTextWidth = paragraph.getMinIntrinsicWidth(unconstrained);
double twoLinesTextHeight = paragraph.getMinIntrinsicHeight(constrained);
// controls
expect(wrappedTextWidth, lessThan(textWidth));
expect(paragraph.getMinIntrinsicWidth(unconstrained), equals(wrappedTextWidth));
expect(paragraph.getMaxIntrinsicWidth(constrained), equals(constrained.maxWidth));
expect(oneLineTextHeight, lessThan(twoLinesTextHeight));
expect(twoLinesTextHeight, lessThan(oneLineTextHeight * 3.0));
expect(paragraph.getMaxIntrinsicHeight(unconstrained), equals(oneLineTextHeight));
expect(paragraph.getMaxIntrinsicHeight(constrained), equals(twoLinesTextHeight));
// test setup
RenderBlock testBlock = new RenderBlock(
children: <RenderBox>[
paragraph,
]
);
final BoxConstraints empty = new BoxConstraints.tight(Size.zero);
// vertical block
expect(testBlock.getMinIntrinsicWidth(unconstrained), equals(wrappedTextWidth));
expect(testBlock.getMinIntrinsicWidth(constrained), equals(wrappedTextWidth));
expect(testBlock.getMaxIntrinsicWidth(unconstrained), equals(textWidth));
expect(testBlock.getMaxIntrinsicWidth(constrained), equals(constrained.maxWidth));
expect(testBlock.getMinIntrinsicHeight(unconstrained), equals(oneLineTextHeight));
expect(testBlock.getMinIntrinsicHeight(constrained), equals(twoLinesTextHeight));
expect(testBlock.getMaxIntrinsicHeight(unconstrained), equals(oneLineTextHeight));
expect(testBlock.getMaxIntrinsicHeight(constrained), equals(twoLinesTextHeight));
expect(testBlock.getMinIntrinsicWidth(empty), equals(0.0));
expect(testBlock.getMaxIntrinsicWidth(empty), equals(0.0));
expect(testBlock.getMinIntrinsicHeight(empty), equals(0.0));
expect(testBlock.getMaxIntrinsicHeight(empty), equals(0.0));
// horizontal block
testBlock.mainAxis = Axis.horizontal;
expect(testBlock.getMinIntrinsicWidth(unconstrained), equals(textWidth));
expect(testBlock.getMinIntrinsicWidth(constrained), equals(constrained.maxWidth));
expect(testBlock.getMaxIntrinsicWidth(unconstrained), equals(textWidth));
expect(testBlock.getMaxIntrinsicWidth(constrained), equals(constrained.maxWidth));
expect(testBlock.getMinIntrinsicHeight(unconstrained), equals(oneLineTextHeight));
expect(testBlock.getMinIntrinsicHeight(constrained), equals(oneLineTextHeight));
expect(testBlock.getMaxIntrinsicHeight(unconstrained), equals(oneLineTextHeight));
expect(testBlock.getMaxIntrinsicHeight(constrained), equals(oneLineTextHeight));
expect(testBlock.getMinIntrinsicWidth(empty), equals(0.0));
expect(testBlock.getMaxIntrinsicWidth(empty), equals(0.0));
expect(testBlock.getMinIntrinsicHeight(empty), equals(0.0));
expect(testBlock.getMaxIntrinsicHeight(empty), equals(0.0));
});
}
...@@ -35,10 +35,10 @@ void main() { ...@@ -35,10 +35,10 @@ void main() {
BoxConstraints viewport = new BoxConstraints(maxHeight: 100.0, maxWidth: 100.0); BoxConstraints viewport = new BoxConstraints(maxHeight: 100.0, maxWidth: 100.0);
layout(flex, constraints: viewport); layout(flex, constraints: viewport);
expect(flexible.size.height, equals(0.0)); expect(flexible.size.height, equals(0.0));
expect(flex.getMinIntrinsicHeight(viewport), equals(100.0)); expect(flex.getMinIntrinsicHeight(100.0), equals(200.0));
expect(flex.getMaxIntrinsicHeight(viewport), equals(100.0)); expect(flex.getMaxIntrinsicHeight(100.0), equals(200.0));
expect(flex.getMinIntrinsicWidth(viewport), equals(100.0)); expect(flex.getMinIntrinsicWidth(100.0), equals(0.0));
expect(flex.getMaxIntrinsicWidth(viewport), equals(100.0)); expect(flex.getMaxIntrinsicWidth(100.0), equals(0.0));
}); });
test('Horizontal Overflow', () { test('Horizontal Overflow', () {
...@@ -57,10 +57,10 @@ void main() { ...@@ -57,10 +57,10 @@ void main() {
BoxConstraints viewport = new BoxConstraints(maxHeight: 100.0, maxWidth: 100.0); BoxConstraints viewport = new BoxConstraints(maxHeight: 100.0, maxWidth: 100.0);
layout(flex, constraints: viewport); layout(flex, constraints: viewport);
expect(flexible.size.width, equals(0.0)); expect(flexible.size.width, equals(0.0));
expect(flex.getMinIntrinsicHeight(viewport), equals(100.0)); expect(flex.getMinIntrinsicHeight(100.0), equals(0.0));
expect(flex.getMaxIntrinsicHeight(viewport), equals(100.0)); expect(flex.getMaxIntrinsicHeight(100.0), equals(0.0));
expect(flex.getMinIntrinsicWidth(viewport), equals(100.0)); expect(flex.getMinIntrinsicWidth(100.0), equals(200.0));
expect(flex.getMaxIntrinsicWidth(viewport), equals(100.0)); expect(flex.getMaxIntrinsicWidth(100.0), equals(200.0));
}); });
test('Vertical Flipped Constraints', () { test('Vertical Flipped Constraints', () {
...@@ -72,7 +72,7 @@ void main() { ...@@ -72,7 +72,7 @@ void main() {
); );
BoxConstraints viewport = new BoxConstraints(maxHeight: 200.0, maxWidth: 1000.0); BoxConstraints viewport = new BoxConstraints(maxHeight: 200.0, maxWidth: 1000.0);
layout(flex, constraints: viewport); layout(flex, constraints: viewport);
expect(flex.getMaxIntrinsicWidth(viewport) , equals(1000.0)); expect(flex.getMaxIntrinsicWidth(200.0), equals(0.0));
}); });
// We can't right a horizontal version of the above test due to // We can't right a horizontal version of the above test due to
......
...@@ -7,29 +7,30 @@ import 'package:test/test.dart'; ...@@ -7,29 +7,30 @@ import 'package:test/test.dart';
import 'rendering_tester.dart'; import 'rendering_tester.dart';
// before using this, consider using RenderSizedBox from rendering_tester.dart
class RenderTestBox extends RenderBox { class RenderTestBox extends RenderBox {
RenderTestBox(this._intrinsicDimensions); RenderTestBox(this._intrinsicDimensions);
final BoxConstraints _intrinsicDimensions; final BoxConstraints _intrinsicDimensions;
@override @override
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(double height) {
return constraints.constrainWidth(_intrinsicDimensions.minWidth); return _intrinsicDimensions.minWidth;
} }
@override @override
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(double height) {
return constraints.constrainWidth(_intrinsicDimensions.maxWidth); return _intrinsicDimensions.maxWidth;
} }
@override @override
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(double width) {
return constraints.constrainHeight(_intrinsicDimensions.minHeight); return _intrinsicDimensions.minHeight;
} }
@override @override
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(double width) {
return constraints.constrainHeight(_intrinsicDimensions.maxHeight); return _intrinsicDimensions.maxHeight;
} }
@override @override
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/rendering.dart';
import 'package:test/test.dart';
void main() {
test('block and paragraph intrinsics', () {
final RenderParagraph paragraph = new RenderParagraph(
new TextSpan(
style: new TextStyle(height: 1.0),
text: 'Hello World'
)
);
final RenderBlock testBlock = new RenderBlock(
children: <RenderBox>[
paragraph,
]
);
final double textWidth = paragraph.getMaxIntrinsicWidth(double.INFINITY);
final double oneLineTextHeight = paragraph.getMinIntrinsicHeight(double.INFINITY);
final double constrainedWidth = textWidth * 0.9;
final double wrappedTextWidth = paragraph.getMinIntrinsicWidth(double.INFINITY);
final double twoLinesTextHeight = paragraph.getMinIntrinsicHeight(constrainedWidth);
final double manyLinesTextHeight = paragraph.getMinIntrinsicHeight(0.0);
// paragraph
expect(wrappedTextWidth, greaterThan(0.0));
expect(wrappedTextWidth, lessThan(textWidth));
expect(oneLineTextHeight, lessThan(twoLinesTextHeight));
expect(twoLinesTextHeight, lessThan(oneLineTextHeight * 3.0));
expect(manyLinesTextHeight, greaterThan(twoLinesTextHeight));
expect(paragraph.getMaxIntrinsicHeight(double.INFINITY), equals(oneLineTextHeight));
expect(paragraph.getMaxIntrinsicHeight(constrainedWidth), equals(twoLinesTextHeight));
expect(paragraph.getMaxIntrinsicHeight(0.0), equals(manyLinesTextHeight));
// vertical block (same expectations)
expect(testBlock.getMinIntrinsicWidth(double.INFINITY), equals(wrappedTextWidth));
expect(testBlock.getMaxIntrinsicWidth(double.INFINITY), equals(textWidth));
expect(testBlock.getMinIntrinsicHeight(double.INFINITY), equals(oneLineTextHeight));
expect(testBlock.getMinIntrinsicHeight(constrainedWidth), equals(twoLinesTextHeight));
expect(testBlock.getMaxIntrinsicHeight(double.INFINITY), equals(oneLineTextHeight));
expect(testBlock.getMaxIntrinsicHeight(constrainedWidth), equals(twoLinesTextHeight));
expect(testBlock.getMinIntrinsicWidth(0.0), equals(wrappedTextWidth));
expect(testBlock.getMaxIntrinsicWidth(0.0), equals(textWidth));
expect(testBlock.getMinIntrinsicHeight(wrappedTextWidth), equals(twoLinesTextHeight));
expect(testBlock.getMaxIntrinsicHeight(wrappedTextWidth), equals(twoLinesTextHeight));
expect(testBlock.getMinIntrinsicHeight(0.0), equals(manyLinesTextHeight));
expect(testBlock.getMaxIntrinsicHeight(0.0), equals(manyLinesTextHeight));
// horizontal block (same expectations again)
testBlock.mainAxis = Axis.horizontal;
expect(testBlock.getMinIntrinsicWidth(double.INFINITY), equals(wrappedTextWidth));
expect(testBlock.getMaxIntrinsicWidth(double.INFINITY), equals(textWidth));
expect(testBlock.getMinIntrinsicHeight(double.INFINITY), equals(oneLineTextHeight));
expect(testBlock.getMinIntrinsicHeight(constrainedWidth), equals(twoLinesTextHeight));
expect(testBlock.getMaxIntrinsicHeight(double.INFINITY), equals(oneLineTextHeight));
expect(testBlock.getMaxIntrinsicHeight(constrainedWidth), equals(twoLinesTextHeight));
expect(testBlock.getMinIntrinsicWidth(0.0), equals(wrappedTextWidth));
expect(testBlock.getMaxIntrinsicWidth(0.0), equals(textWidth));
expect(testBlock.getMinIntrinsicHeight(wrappedTextWidth), equals(twoLinesTextHeight));
expect(testBlock.getMaxIntrinsicHeight(wrappedTextWidth), equals(twoLinesTextHeight));
expect(testBlock.getMinIntrinsicHeight(0.0), equals(manyLinesTextHeight));
expect(testBlock.getMaxIntrinsicHeight(0.0), equals(manyLinesTextHeight));
});
}
...@@ -91,7 +91,33 @@ class RenderSizedBox extends RenderBox { ...@@ -91,7 +91,33 @@ class RenderSizedBox extends RenderBox {
final Size _size; final Size _size;
@override @override
void performLayout() { double getMinIntrinsicWidth(double height) {
return _size.width;
}
@override
double getMaxIntrinsicWidth(double height) {
return _size.width;
}
@override
double getMinIntrinsicHeight(double width) {
return _size.height;
}
@override
double getMaxIntrinsicHeight(double width) {
return _size.height;
}
@override
bool get sizedByParent => true;
@override
void performResize() {
size = constraints.constrain(_size); size = constraints.constrain(_size);
} }
@override
void performLayout() { }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment