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
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
double getMinIntrinsicWidth(double height) {
if (child == null)
return super.getMinIntrinsicWidth(constraints);
return getIntrinsicDimensions(constraints).width;
return 0.0;
return getIntrinsicDimensions(height: height).width;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
double getMaxIntrinsicWidth(double height) {
if (child == null)
return super.getMaxIntrinsicWidth(constraints);
return getIntrinsicDimensions(constraints).width;
return 0.0;
return getIntrinsicDimensions(height: height).width;
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
double getMinIntrinsicHeight(double width) {
if (child == null)
return super.getMinIntrinsicHeight(constraints);
return getIntrinsicDimensions(constraints).height;
return 0.0;
return getIntrinsicDimensions(width: width).height;
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
double getMaxIntrinsicHeight(double width) {
if (child == null)
return super.getMaxIntrinsicHeight(constraints);
return getIntrinsicDimensions(constraints).height;
return 0.0;
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.parentData is SectorParentData);
assert(constraints.maxWidth < double.INFINITY || constraints.maxHeight < double.INFINITY);
double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius;
assert(width != null);
assert(height != null);
double maxChildDeltaRadius = math.min(width, height) / 2.0 - innerRadius;
SectorDimensions childDimensions = child.getIntrinsicDimensions(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), innerRadius);
double dimension = (innerRadius + childDimensions.deltaRadius) * 2.0;
return constraints.constrain(new Size(dimension, dimension));
......
......@@ -14,31 +14,23 @@ class RenderSolidColorBox extends RenderDecoratedBox {
super(decoration: new BoxDecoration(backgroundColor: backgroundColor));
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
return constraints.constrainHeight(
this.desiredSize == Size.infinite ? 0.0 : desiredSize.width
);
double getMinIntrinsicWidth(double height) {
return desiredSize.width == double.INFINITY ? 0.0 : desiredSize.width;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
return constraints.constrainWidth(
this.desiredSize == Size.infinite ? 0.0 : desiredSize.width
);
double getMaxIntrinsicWidth(double height) {
return desiredSize.width == double.INFINITY ? 0.0 : desiredSize.width;
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
return constraints.constrainHeight(
this.desiredSize == Size.infinite ? 0.0 : desiredSize.height
);
double getMinIntrinsicHeight(double width) {
return desiredSize.height == double.INFINITY ? 0.0 : desiredSize.height;
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
return constraints.constrainHeight(
this.desiredSize == Size.infinite ? 0.0 : desiredSize.height
);
double getMaxIntrinsicHeight(double width) {
return desiredSize.height == double.INFINITY ? 0.0 : desiredSize.height;
}
@override
......
......@@ -100,47 +100,40 @@ class _RenderTabBar extends RenderBox with
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
BoxConstraints widthConstraints =
new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraints.maxHeight);
double getMinIntrinsicWidth(double height) {
double maxWidth = 0.0;
RenderBox child = firstChild;
while (child != null) {
maxWidth = math.max(maxWidth, child.getMinIntrinsicWidth(widthConstraints));
maxWidth = math.max(maxWidth, child.getMinIntrinsicWidth(height));
final _TabBarParentData childParentData = child.parentData;
child = childParentData.nextSibling;
}
double width = isScrollable ? maxWidth : maxWidth * childCount;
return constraints.constrainWidth(width);
return isScrollable ? maxWidth : maxWidth * childCount;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
BoxConstraints widthConstraints =
new BoxConstraints(maxWidth: constraints.maxWidth, maxHeight: constraints.maxHeight);
double getMaxIntrinsicWidth(double height) {
double maxWidth = 0.0;
double totalWidth = 0.0;
RenderBox child = firstChild;
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;
child = childParentData.nextSibling;
}
double width = isScrollable ? maxWidth : maxWidth * childCount;
return constraints.constrainWidth(width);
return isScrollable ? totalWidth : maxWidth * childCount;
}
double get _tabHeight => textAndIcons ? _kTextAndIconTabHeight : _kTabHeight;
double get _tabBarHeight => _tabHeight + _kTabIndicatorHeight;
double _getIntrinsicHeight(BoxConstraints constraints) => constraints.constrainHeight(_tabBarHeight);
@override
double getMinIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeight(constraints);
double getMinIntrinsicHeight(double width) => _tabBarHeight;
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) => _getIntrinsicHeight(constraints);
double getMaxIntrinsicHeight(double width) => _tabBarHeight;
void layoutFixedWidthTabs() {
double tabWidth = size.width / childCount;
......
......@@ -10,8 +10,7 @@ import 'object.dart';
/// Parent data for use with [RenderBlockBase].
class BlockParentData extends ContainerBoxParentDataMixin<RenderBox> { }
typedef double _ChildSizingFunction(RenderBox child, BoxConstraints constraints);
typedef double _Constrainer(double value);
typedef double _ChildSizingFunction(RenderBox child);
/// Implements the block layout algorithm.
///
......@@ -158,102 +157,65 @@ class RenderBlock extends RenderBox
description.add('mainAxis: $mainAxis');
}
double _getIntrinsicCrossAxis(BoxConstraints constraints, _ChildSizingFunction childSize, _Constrainer constrainer) {
double _getIntrinsicCrossAxis(_ChildSizingFunction childSize) {
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;
while (child != null) {
extent = math.max(extent, childSize(child, innerConstraints));
extent = math.max(extent, childSize(child));
final BlockParentData childParentData = child.parentData;
child = childParentData.nextSibling;
}
return constrainer(extent);
return extent;
}
double _getIntrinsicMainAxis(BoxConstraints constraints, _Constrainer constrainer) {
double _getIntrinsicMainAxis(_ChildSizingFunction childSize) {
double extent = 0.0;
BoxConstraints innerConstraints = _getInnerConstraints(constraints);
RenderBox child = firstChild;
while (child != null) {
switch (mainAxis) {
case Axis.horizontal:
extent += child.getMaxIntrinsicWidth(innerConstraints);
break;
case Axis.vertical:
extent += child.getMinIntrinsicHeight(innerConstraints);
break;
}
extent += childSize(child);
final BlockParentData childParentData = child.parentData;
child = childParentData.nextSibling;
}
return constrainer(extent);
return extent;
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double getMinIntrinsicWidth(double height) {
switch (mainAxis) {
case Axis.horizontal:
return _getIntrinsicMainAxis(constraints, constraints.constrainWidth);
return _getIntrinsicMainAxis((RenderBox child) => child.getMinIntrinsicWidth(height));
case Axis.vertical:
return _getIntrinsicCrossAxis(
constraints,
(RenderBox child, BoxConstraints innerConstraints) => child.getMinIntrinsicWidth(innerConstraints),
constraints.constrainWidth
);
return _getIntrinsicCrossAxis((RenderBox child) => child.getMinIntrinsicWidth(height));
}
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double getMaxIntrinsicWidth(double height) {
switch (mainAxis) {
case Axis.horizontal:
return _getIntrinsicMainAxis(constraints, constraints.constrainWidth);
return _getIntrinsicMainAxis((RenderBox child) => child.getMaxIntrinsicWidth(height));
case Axis.vertical:
return _getIntrinsicCrossAxis(
constraints,
(RenderBox child, BoxConstraints innerConstraints) => child.getMaxIntrinsicWidth(innerConstraints),
constraints.constrainWidth
);
return _getIntrinsicCrossAxis((RenderBox child) => child.getMaxIntrinsicWidth(height));
}
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double getMinIntrinsicHeight(double width) {
switch (mainAxis) {
case Axis.horizontal:
return _getIntrinsicCrossAxis(
constraints,
(RenderBox child, BoxConstraints innerConstraints) => child.getMinIntrinsicHeight(innerConstraints),
constraints.constrainHeight
);
return _getIntrinsicMainAxis((RenderBox child) => child.getMinIntrinsicHeight(width));
case Axis.vertical:
return _getIntrinsicMainAxis(constraints, constraints.constrainHeight);
return _getIntrinsicCrossAxis((RenderBox child) => child.getMinIntrinsicHeight(width));
}
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double getMaxIntrinsicHeight(double width) {
switch (mainAxis) {
case Axis.horizontal:
return _getIntrinsicCrossAxis(
constraints,
(RenderBox child, BoxConstraints innerConstraints) => child.getMaxIntrinsicHeight(innerConstraints),
constraints.constrainHeight
);
return _getIntrinsicMainAxis((RenderBox child) => child.getMaxIntrinsicHeight(width));
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
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
double getMinIntrinsicWidth(BoxConstraints constraints) {
return _getSize(constraints).width;
double getMinIntrinsicWidth(double height) {
final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
if (width.isFinite)
return width;
return 0.0;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
return _getSize(constraints).width;
double getMaxIntrinsicWidth(double height) {
final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
if (width.isFinite)
return width;
return 0.0;
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
return _getSize(constraints).height;
double getMinIntrinsicHeight(double width) {
final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
if (height.isFinite)
return height;
return 0.0;
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
return _getSize(constraints).height;
double getMaxIntrinsicHeight(double width) {
final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
if (height.isFinite)
return height;
return 0.0;
}
@override
......
......@@ -192,27 +192,13 @@ class RenderEditableLine extends RenderBox {
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return constraints.constrainWidth(0.0);
double getMinIntrinsicHeight(double width) {
return _preferredHeight;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
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);
double getMaxIntrinsicHeight(double width) {
return _preferredHeight;
}
@override
......
......@@ -54,23 +54,13 @@ class RenderErrorBox extends RenderBox {
ui.Paragraph _paragraph;
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
return constraints.constrainWidth(0.0);
double getMaxIntrinsicWidth(double height) {
return _kMaxWidth;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
return constraints.constrainWidth(_kMaxWidth);
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
return constraints.constrainHeight(0.0);
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
return constraints.constrainHeight(_kMaxHeight);
double getMaxIntrinsicHeight(double width) {
return _kMaxHeight;
}
@override
......
......@@ -71,7 +71,7 @@ enum CrossAxisAlignment {
baseline,
}
typedef double _ChildSizingFunction(RenderBox child, BoxConstraints constraints);
typedef double _ChildSizingFunction(RenderBox child, double extent);
/// Implements the flex layout algorithm
///
......@@ -156,25 +156,15 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
child.parentData = new FlexParentData();
}
double _getIntrinsicSize({ BoxConstraints constraints,
FlexDirection sizingDirection,
_ChildSizingFunction childSize }) {
assert(constraints.debugAssertIsValid());
// http://www.w3.org/TR/2015/WD-css-flexbox-1-20150514/#intrinsic-sizes
double _getIntrinsicSize({
FlexDirection sizingDirection,
double extent, // the extent in the direction that isn't the sizing direction
_ChildSizingFunction childSize // a method to find the size in the sizing direction
}) {
if (_direction == sizingDirection) {
// INTRINSIC MAIN SIZE
// Intrinsic main size is the smallest size the flex container can take
// 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 inflexibleSpace = 0.0;
double maxFlexFractionSoFar = 0.0;
......@@ -183,47 +173,24 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
int flex = _getFlex(child);
totalFlex += flex;
if (flex > 0) {
double flexFraction = childSize(child, childConstraints) / _getFlex(child);
double flexFraction = childSize(child, extent) / _getFlex(child);
maxFlexFractionSoFar = math.max(maxFlexFractionSoFar, flexFraction);
} else {
inflexibleSpace += childSize(child, childConstraints);
inflexibleSpace += childSize(child, extent);
}
final FlexParentData childParentData = child.parentData;
child = childParentData.nextSibling;
}
double mainSize = 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);
}
return maxFlexFractionSoFar * totalFlex + inflexibleSpace;
} else {
// INTRINSIC CROSS SIZE
// The spec wants us to perform layout into the given available main-axis
// space and return the cross size. That's too expensive, so instead we
// size inflexible children according to their max intrinsic size in the
// main direction and use those constraints to determine their max
// 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;
}
// Intrinsic cross size is the max of the intrinsic cross sizes of the
// children, after the flexible children are fit into the available space,
// with the children sized using their max intrinsic dimensions.
// TODO(ianh): Support baseline alignment.
// 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;
double inflexibleSpace = 0.0;
double maxCrossSize = 0.0;
......@@ -236,16 +203,12 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
if (flex == 0) {
switch (_direction) {
case FlexDirection.horizontal:
mainSize = child.getMaxIntrinsicWidth(childConstraints);
BoxConstraints widthConstraints =
new BoxConstraints(minWidth: mainSize, maxWidth: mainSize);
crossSize = child.getMaxIntrinsicHeight(widthConstraints);
mainSize = child.getMaxIntrinsicWidth(double.INFINITY);
crossSize = childSize(child, mainSize);
break;
case FlexDirection.vertical:
mainSize = child.getMaxIntrinsicHeight(childConstraints);
BoxConstraints heightConstraints =
new BoxConstraints(minWidth: mainSize, maxWidth: mainSize);
crossSize = child.getMaxIntrinsicWidth(heightConstraints);
mainSize = child.getMaxIntrinsicHeight(double.INFINITY);
crossSize = childSize(child, mainSize);
break;
}
inflexibleSpace += mainSize;
......@@ -255,79 +218,59 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
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.
double spacePerFlex = math.max(0.0,
(availableMainSpace - inflexibleSpace) / totalFlex);
// Size remaining items, find the maximum cross size
// Size remaining (flexible) items, find the maximum cross size.
child = firstChild;
while (child != null) {
int flex = _getFlex(child);
if (flex > 0) {
double childMainSize = 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);
}
if (flex > 0)
maxCrossSize = math.max(maxCrossSize, childSize(child, spacePerFlex * flex));
final FlexParentData childParentData = child.parentData;
child = childParentData.nextSibling;
}
// Ensure that we don't violate the given constraints with our result
switch(_direction) {
case FlexDirection.horizontal:
return constraints.constrainHeight(maxCrossSize);
case FlexDirection.vertical:
return constraints.constrainWidth(maxCrossSize);
}
return maxCrossSize;
}
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
double getMinIntrinsicWidth(double height) {
return _getIntrinsicSize(
constraints: constraints,
sizingDirection: FlexDirection.horizontal,
childSize: (RenderBox child, BoxConstraints innerConstraints) => child.getMinIntrinsicWidth(innerConstraints)
extent: height,
childSize: (RenderBox child, double extent) => child.getMinIntrinsicWidth(extent)
);
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
double getMaxIntrinsicWidth(double height) {
return _getIntrinsicSize(
constraints: constraints,
sizingDirection: FlexDirection.horizontal,
childSize: (RenderBox child, BoxConstraints innerConstraints) => child.getMaxIntrinsicWidth(innerConstraints)
extent: height,
childSize: (RenderBox child, double extent) => child.getMaxIntrinsicWidth(extent)
);
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
double getMinIntrinsicHeight(double width) {
return _getIntrinsicSize(
constraints: constraints,
sizingDirection: FlexDirection.vertical,
childSize: (RenderBox child, BoxConstraints innerConstraints) => child.getMinIntrinsicHeight(innerConstraints)
extent: width,
childSize: (RenderBox child, double extent) => child.getMinIntrinsicHeight(extent)
);
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
double getMaxIntrinsicHeight(double width) {
return _getIntrinsicSize(
constraints: constraints,
sizingDirection: FlexDirection.vertical,
childSize: (RenderBox child, BoxConstraints innerConstraints) => child.getMaxIntrinsicHeight(innerConstraints));
extent: width,
childSize: (RenderBox child, double extent) => child.getMaxIntrinsicHeight(extent)
);
}
@override
......@@ -352,8 +295,6 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
@override
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.
int totalFlex = 0;
int totalChildren = 0;
......
......@@ -240,24 +240,40 @@ class RenderFlow extends RenderBox
@override
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
double getMinIntrinsicWidth(BoxConstraints constraints) {
return _getSize(constraints).width;
double getMinIntrinsicWidth(double height) {
final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
if (width.isFinite)
return width;
return 0.0;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
return _getSize(constraints).width;
double getMaxIntrinsicWidth(double height) {
final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
if (width.isFinite)
return width;
return 0.0;
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
return _getSize(constraints).height;
double getMinIntrinsicHeight(double width) {
final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
if (height.isFinite)
return height;
return 0.0;
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
return _getSize(constraints).height;
double getMaxIntrinsicHeight(double width) {
final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
if (height.isFinite)
return height;
return 0.0;
}
@override
......
......@@ -181,26 +181,34 @@ abstract class GridDelegate {
/// Returns the minimum width that this grid could be without failing to paint
/// 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
/// 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
/// 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
/// 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
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints, int childCount) {
return constraints.constrainWidth(0.0);
double getMinIntrinsicWidth(double height, int childCount) {
return 0.0;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints, int childCount) {
return constraints.constrainWidth(0.0);
double getMaxIntrinsicWidth(double height, int childCount) {
return 0.0;
}
}
......@@ -359,13 +367,13 @@ class MaxTileWidthGridDelegate extends GridDelegateWithInOrderChildPlacement {
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints, int childCount) {
return constraints.constrainWidth(0.0);
double getMinIntrinsicWidth(double height, int childCount) {
return 0.0;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints, int childCount) {
return constraints.constrainWidth(maxTileWidth * childCount);
double getMaxIntrinsicWidth(double height, int childCount) {
return maxTileWidth * childCount;
}
}
......@@ -470,27 +478,23 @@ class RenderGrid extends RenderVirtualViewport<GridParentData> {
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return _delegate.getMinIntrinsicWidth(constraints, virtualChildCount);
double getMinIntrinsicWidth(double height) {
return _delegate.getMinIntrinsicWidth(height, virtualChildCount);
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return _delegate.getMaxIntrinsicWidth(constraints, virtualChildCount);
double getMaxIntrinsicWidth(double height) {
return _delegate.getMaxIntrinsicWidth(height, virtualChildCount);
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return _delegate.getMinIntrinsicHeight(constraints, virtualChildCount);
double getMinIntrinsicHeight(double width) {
return _delegate.getMinIntrinsicHeight(width, virtualChildCount);
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return _delegate.getMaxIntrinsicHeight(constraints, virtualChildCount);
double getMaxIntrinsicHeight(double width) {
return _delegate.getMaxIntrinsicHeight(width, virtualChildCount);
}
@override
......
......@@ -205,31 +205,27 @@ class RenderImage extends RenderBox {
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double getMinIntrinsicWidth(double height) {
if (_width == null && _height == null)
return constraints.constrainWidth(0.0);
return _sizeForConstraints(constraints).width;
return 0.0;
return _sizeForConstraints(new BoxConstraints.tightForFinite(height: height)).width;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return _sizeForConstraints(constraints).width;
double getMaxIntrinsicWidth(double height) {
return _sizeForConstraints(new BoxConstraints.tightForFinite(height: height)).width;
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double getMinIntrinsicHeight(double width) {
if (_width == null && _height == null)
return constraints.constrainHeight(0.0);
return _sizeForConstraints(constraints).height;
return 0.0;
return _sizeForConstraints(new BoxConstraints.tightForFinite(width: width)).height;
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return _sizeForConstraints(constraints).height;
double getMaxIntrinsicHeight(double width) {
return _sizeForConstraints(new BoxConstraints.tightForFinite(width: width)).height;
}
@override
......
......@@ -87,7 +87,7 @@ class RenderList extends RenderVirtualViewport<ListParentData> {
double get _preferredExtent {
if (itemExtent == null)
return double.INFINITY;
int count = virtualChildCount;
final int count = virtualChildCount;
if (count == null)
return double.INFINITY;
double extent = itemExtent * count;
......@@ -96,44 +96,52 @@ class RenderList extends RenderVirtualViewport<ListParentData> {
return extent;
}
double _getIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double _getIntrinsicWidth() {
switch (mainAxis) {
case Axis.vertical:
return constraints.constrainWidth(0.0);
assert(debugThrowIfNotCheckingIntrinsics());
return 0.0;
case Axis.horizontal:
return constraints.constrainWidth(_preferredExtent);
final double width = _preferredExtent;
if (width.isFinite)
return width;
assert(debugThrowIfNotCheckingIntrinsics());
return 0.0;
}
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
return _getIntrinsicWidth(constraints);
double getMinIntrinsicWidth(double height) {
return _getIntrinsicWidth();
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
return _getIntrinsicWidth(constraints);
double getMaxIntrinsicWidth(double height) {
return _getIntrinsicWidth();
}
double _getIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double _getIntrinsicHeight() {
switch (mainAxis) {
case Axis.vertical:
return constraints.constrainHeight(_preferredExtent);
final double height = _preferredExtent;
if (height.isFinite)
return height;
assert(debugThrowIfNotCheckingIntrinsics());
return 0.0;
case Axis.horizontal:
return constraints.constrainHeight(0.0);
assert(debugThrowIfNotCheckingIntrinsics());
return 0.0;
}
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
return _getIntrinsicHeight(constraints);
double getMinIntrinsicHeight(double width) {
return _getIntrinsicHeight();
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
return _getIntrinsicHeight(constraints);
double getMaxIntrinsicHeight(double width) {
return _getIntrinsicHeight();
}
@override
......
......@@ -14,18 +14,6 @@ class RenderOffStage extends RenderBox with RenderObjectWithChildMixin<RenderBox
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
bool get sizedByParent => true;
......
......@@ -87,45 +87,43 @@ class RenderParagraph extends RenderBox {
markNeedsPaint();
}
void _layoutText(BoxConstraints constraints) {
assert(constraints != null);
assert(constraints.debugAssertIsValid());
_textPainter.layout(minWidth: constraints.minWidth, maxWidth: _softWrap ? constraints.maxWidth : double.INFINITY);
void _layoutText({ double minWidth: 0.0, double maxWidth: double.INFINITY }) {
_textPainter.layout(minWidth: minWidth, maxWidth: _softWrap ? maxWidth : double.INFINITY);
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
_layoutText(constraints);
return constraints.constrainWidth(_textPainter.minIntrinsicWidth);
double getMinIntrinsicWidth(double height) {
_layoutText();
return _textPainter.minIntrinsicWidth;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
_layoutText(constraints);
return constraints.constrainWidth(_textPainter.maxIntrinsicWidth);
double getMaxIntrinsicWidth(double height) {
_layoutText();
return _textPainter.maxIntrinsicWidth;
}
double _getIntrinsicHeight(BoxConstraints constraints) {
_layoutText(constraints);
return constraints.constrainHeight(_textPainter.height);
double _getIntrinsicHeight(double width) {
_layoutText(minWidth: width, maxWidth: width);
return _textPainter.height;
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return _getIntrinsicHeight(constraints);
double getMinIntrinsicHeight(double width) {
return _getIntrinsicHeight(width);
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return _getIntrinsicHeight(constraints);
double getMaxIntrinsicHeight(double width) {
return _getIntrinsicHeight(width);
}
@override
double computeDistanceToActualBaseline(TextBaseline baseline) {
assert(!needsLayout);
_layoutText(constraints);
assert(constraints != null);
assert(constraints.debugAssertIsValid());
_layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
return _textPainter.computeDistanceToActualBaseline(baseline);
}
......@@ -136,7 +134,7 @@ class RenderParagraph extends RenderBox {
void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
if (event is! PointerDownEvent)
return;
_layoutText(constraints);
_layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
Offset offset = entry.localPosition.toOffset();
TextPosition position = _textPainter.getPositionForOffset(offset);
TextSpan span = _textPainter.text.getSpanForPosition(position);
......@@ -149,7 +147,7 @@ class RenderParagraph extends RenderBox {
@override
void performLayout() {
_layoutText(constraints);
_layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
size = constraints.constrain(_textPainter.size);
final bool didOverflowWidth = size.width < _textPainter.width;
......@@ -200,7 +198,7 @@ class RenderParagraph extends RenderBox {
//
// If you remove this call, make sure that changing the textAlign still
// works properly.
_layoutText(constraints);
_layoutText(minWidth: constraints.minWidth, maxWidth: constraints.maxWidth);
final Canvas canvas = context.canvas;
if (_hasVisualOverflow) {
final Rect bounds = offset & size;
......
......@@ -97,13 +97,13 @@ class RenderPerformanceOverlay extends RenderBox {
bool get alwaysNeedsCompositing => true;
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
return constraints.constrainWidth(0.0);
double getMinIntrinsicWidth(double height) {
return 0.0;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
return constraints.constrainWidth(0.0);
double getMaxIntrinsicWidth(double height) {
return 0.0;
}
double get _intrinsicHeight {
......@@ -119,13 +119,13 @@ class RenderPerformanceOverlay extends RenderBox {
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
return constraints.constrainHeight(_intrinsicHeight);
double getMinIntrinsicHeight(double width) {
return _intrinsicHeight;
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
return constraints.constrainHeight(_intrinsicHeight);
double getMaxIntrinsicHeight(double width) {
return _intrinsicHeight;
}
@override
......
......@@ -43,35 +43,31 @@ class RenderRotatedBox extends RenderBox with RenderObjectWithChildMixin<RenderB
bool get _isVertical => quarterTurns % 2 == 1;
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
if (child != null)
return _isVertical ? child.getMinIntrinsicHeight(constraints.flipped) : child.getMinIntrinsicWidth(constraints);
return super.getMinIntrinsicWidth(constraints);
double getMinIntrinsicWidth(double height) {
if (child == null)
return 0.0;
return _isVertical ? child.getMinIntrinsicHeight(height) : child.getMinIntrinsicWidth(height);
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
if (child != null)
return _isVertical ? child.getMaxIntrinsicHeight(constraints.flipped) : child.getMaxIntrinsicWidth(constraints);
return super.getMaxIntrinsicWidth(constraints);
double getMaxIntrinsicWidth(double height) {
if (child == null)
return 0.0;
return _isVertical ? child.getMaxIntrinsicHeight(height) : child.getMaxIntrinsicWidth(height);
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
if (child != null)
return _isVertical ? child.getMinIntrinsicWidth(constraints.flipped) : child.getMinIntrinsicHeight(constraints);
return super.getMinIntrinsicHeight(constraints);
double getMinIntrinsicHeight(double width) {
if (child == null)
return 0.0;
return _isVertical ? child.getMinIntrinsicWidth(width) : child.getMinIntrinsicHeight(width);
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
if (child != null)
return _isVertical ? child.getMaxIntrinsicWidth(constraints.flipped) : child.getMaxIntrinsicHeight(constraints);
return super.getMaxIntrinsicHeight(constraints);
double getMaxIntrinsicHeight(double width) {
if (child == null)
return 0.0;
return _isVertical ? child.getMaxIntrinsicWidth(width) : child.getMaxIntrinsicHeight(width);
}
Matrix4 _paintTransform;
......
......@@ -224,78 +224,37 @@ abstract class RenderStackBase extends RenderBox
}
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double width = constraints.minWidth;
double _getIntrinsicDimension(double mainChildSizeGetter(RenderBox child)) {
double extent = 0.0;
RenderBox child = firstChild;
while (child != null) {
final StackParentData childParentData = child.parentData;
if (!childParentData.isPositioned)
width = math.max(width, child.getMinIntrinsicWidth(constraints));
extent = math.max(extent, mainChildSizeGetter(child));
assert(child.parentData == childParentData);
child = childParentData.nextSibling;
}
assert(width == constraints.constrainWidth(width));
return width;
return extent;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
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;
double getMinIntrinsicWidth(double height) {
return _getIntrinsicDimension((RenderBox child) => child.getMinIntrinsicWidth(height));
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
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;
double getMaxIntrinsicWidth(double height) {
return _getIntrinsicDimension((RenderBox child) => child.getMaxIntrinsicWidth(height));
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
bool hasNonPositionedChildren = false;
double height = constraints.minHeight;
RenderBox child = firstChild;
while (child != null) {
final StackParentData childParentData = child.parentData;
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;
double getMinIntrinsicHeight(double width) {
return _getIntrinsicDimension((RenderBox child) => child.getMinIntrinsicHeight(width));
}
@override
double getMaxIntrinsicHeight(double width) {
return _getIntrinsicDimension((RenderBox child) => child.getMaxIntrinsicHeight(width));
}
@override
......
......@@ -82,7 +82,7 @@ class IntrinsicColumnWidth extends TableColumnWidth {
double minIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
double result = 0.0;
for (RenderBox cell in cells)
result = math.max(result, cell.getMinIntrinsicWidth(const BoxConstraints()));
result = math.max(result, cell.getMinIntrinsicWidth(double.INFINITY));
return result;
}
......@@ -90,7 +90,7 @@ class IntrinsicColumnWidth extends TableColumnWidth {
double maxIntrinsicWidth(Iterable<RenderBox> cells, double containerWidth) {
double result = 0.0;
for (RenderBox cell in cells)
result = math.max(result, cell.getMaxIntrinsicWidth(const BoxConstraints()));
result = math.max(result, cell.getMaxIntrinsicWidth(double.INFINITY));
return result;
}
......@@ -689,36 +689,33 @@ class RenderTable extends RenderBox {
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double getMinIntrinsicWidth(double height) {
assert(_children.length == rows * columns);
double totalMinWidth = 0.0;
for (int x = 0; x < columns; x += 1) {
TableColumnWidth columnWidth = _columnWidths[x] ?? defaultColumnWidth;
Iterable<RenderBox> columnCells = column(x);
totalMinWidth += columnWidth.minIntrinsicWidth(columnCells, constraints.maxWidth);
totalMinWidth += columnWidth.minIntrinsicWidth(columnCells, double.INFINITY);
}
return constraints.constrainWidth(totalMinWidth);
return totalMinWidth;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double getMaxIntrinsicWidth(double height) {
assert(_children.length == rows * columns);
double totalMaxWidth = 0.0;
for (int x = 0; x < columns; x += 1) {
TableColumnWidth columnWidth = _columnWidths[x] ?? defaultColumnWidth;
Iterable<RenderBox> columnCells = column(x);
totalMaxWidth += columnWidth.maxIntrinsicWidth(columnCells, constraints.maxWidth);
totalMaxWidth += columnWidth.maxIntrinsicWidth(columnCells, double.INFINITY);
}
return constraints.constrainWidth(totalMaxWidth);
return totalMaxWidth;
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
double getMinIntrinsicHeight(double width) {
// winner of the 2016 world's most expensive intrinsic dimension function award
// honorable mention, most likely to improve if taught about memoization award
assert(constraints.debugAssertIsValid());
assert(_children.length == rows * columns);
final List<double> widths = _computeColumnWidths(constraints);
double rowTop = 0.0;
......@@ -728,16 +725,16 @@ class RenderTable extends RenderBox {
final int xy = x + y * columns;
RenderBox child = _children[xy];
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;
}
return constraints.constrainHeight(rowTop);
return rowTop;
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
return getMinIntrinsicHeight(constraints);
double getMaxIntrinsicHeight(double width) {
return getMinIntrinsicHeight(width);
}
double _baselineDistance;
......
......@@ -218,35 +218,31 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
}
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double getMinIntrinsicWidth(double height) {
if (child != null)
return constraints.constrainWidth(child.getMinIntrinsicWidth(_getInnerConstraints(constraints)));
return super.getMinIntrinsicWidth(constraints);
return child.getMinIntrinsicWidth(height);
return 0.0;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double getMaxIntrinsicWidth(double height) {
if (child != null)
return constraints.constrainWidth(child.getMaxIntrinsicWidth(_getInnerConstraints(constraints)));
return super.getMaxIntrinsicWidth(constraints);
return child.getMaxIntrinsicWidth(height);
return 0.0;
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double getMinIntrinsicHeight(double width) {
if (child != null)
return constraints.constrainHeight(child.getMinIntrinsicHeight(_getInnerConstraints(constraints)));
return super.getMinIntrinsicHeight(constraints);
return child.getMinIntrinsicHeight(width);
return 0.0;
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
double getMaxIntrinsicHeight(double width) {
if (child != null)
return constraints.constrainHeight(child.getMaxIntrinsicHeight(_getInnerConstraints(constraints)));
return super.getMaxIntrinsicHeight(constraints);
return child.getMaxIntrinsicHeight(width);
return 0.0;
}
// We don't override computeDistanceToActualBaseline(), because we
......@@ -353,6 +349,51 @@ abstract class RenderVirtualViewport<T extends ContainerBoxParentDataMixin<Rende
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
bool hitTestChildren(HitTestResult result, { Point position }) {
return defaultHitTestChildren(result, position: position + -_effectivePaintOffset);
......
......@@ -44,32 +44,42 @@ class _RenderLayoutBuilder extends RenderBox with RenderObjectWithChildMixin<Ren
markNeedsLayout();
}
double getIntrinsicWidth(BoxConstraints constraints) => constraints.constrainWidth();
double getIntrinsicHeight(BoxConstraints constraints) => constraints.constrainHeight();
bool _debugThrowIfNotCheckingIntrinsics() {
assert(() {
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
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return getIntrinsicWidth(constraints);
double getMinIntrinsicWidth(double height) {
assert(_debugThrowIfNotCheckingIntrinsics());
return 0.0;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return getIntrinsicWidth(constraints);
double getMaxIntrinsicWidth(double height) {
assert(_debugThrowIfNotCheckingIntrinsics());
return 0.0;
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return getIntrinsicHeight(constraints);
double getMinIntrinsicHeight(double width) {
assert(_debugThrowIfNotCheckingIntrinsics());
return 0.0;
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return getIntrinsicHeight(constraints);
double getMaxIntrinsicHeight(double width) {
assert(_debugThrowIfNotCheckingIntrinsics());
return 0.0;
}
@override
......@@ -85,7 +95,7 @@ class _RenderLayoutBuilder extends RenderBox with RenderObjectWithChildMixin<Ren
if (callback != null)
invokeLayoutCallback(callback);
if (child != null)
child.layout(constraints.loosen(), parentUsesSize: false);
child.layout(constraints.loosen());
}
@override
......
......@@ -368,48 +368,28 @@ class _RenderLazyBlock extends RenderVirtualViewport<_LazyBlockParentData> {
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
double getMinIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return getIntrinsicWidth(constraints);
double getMinIntrinsicWidth(double height) {
assert(_debugThrowIfNotCheckingIntrinsics());
return 0.0;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return getIntrinsicWidth(constraints);
}
double getIntrinsicHeight(BoxConstraints constraints) {
switch (mainAxis) {
case Axis.horizontal:
return constraints.constrainHeight(0.0);
case Axis.vertical:
assert(_debugThrowIfNotCheckingIntrinsics());
return constraints.constrainHeight(0.0);
}
double getMaxIntrinsicWidth(double height) {
assert(_debugThrowIfNotCheckingIntrinsics());
return 0.0;
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return getIntrinsicHeight(constraints);
double getMinIntrinsicHeight(double width) {
assert(_debugThrowIfNotCheckingIntrinsics());
return 0.0;
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
return getIntrinsicHeight(constraints);
double getMaxIntrinsicHeight(double width) {
assert(_debugThrowIfNotCheckingIntrinsics());
return 0.0;
}
@override
......
......@@ -4,21 +4,96 @@
import 'package:flutter/rendering.dart';
import 'package:test/test.dart';
import 'rendering_tester.dart';
void main() {
test('Intrinsic sizing', () {
test('Intrinsic sizing 2.0', () {
RenderAspectRatio box = new RenderAspectRatio(aspectRatio: 2.0);
BoxConstraints constraints = new BoxConstraints.loose(new Size(200.0, 200.0));
expect(box.getMinIntrinsicWidth(constraints), equals(0.0));
expect(box.getMaxIntrinsicWidth(constraints), equals(200.0));
expect(box.getMinIntrinsicHeight(constraints), equals(0.0));
expect(box.getMaxIntrinsicHeight(constraints), equals(100.0));
constraints = new BoxConstraints(maxHeight: 400.0);
expect(box.getMinIntrinsicWidth(constraints), equals(0.0));
expect(box.getMaxIntrinsicWidth(constraints), equals(800.0));
expect(box.getMinIntrinsicHeight(constraints), equals(0.0));
expect(box.getMaxIntrinsicHeight(constraints), equals(400.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), 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() {
BoxConstraints viewport = new BoxConstraints(maxHeight: 100.0, maxWidth: 100.0);
layout(flex, constraints: viewport);
expect(flexible.size.height, equals(0.0));
expect(flex.getMinIntrinsicHeight(viewport), equals(100.0));
expect(flex.getMaxIntrinsicHeight(viewport), equals(100.0));
expect(flex.getMinIntrinsicWidth(viewport), equals(100.0));
expect(flex.getMaxIntrinsicWidth(viewport), equals(100.0));
expect(flex.getMinIntrinsicHeight(100.0), equals(200.0));
expect(flex.getMaxIntrinsicHeight(100.0), equals(200.0));
expect(flex.getMinIntrinsicWidth(100.0), equals(0.0));
expect(flex.getMaxIntrinsicWidth(100.0), equals(0.0));
});
test('Horizontal Overflow', () {
......@@ -57,10 +57,10 @@ void main() {
BoxConstraints viewport = new BoxConstraints(maxHeight: 100.0, maxWidth: 100.0);
layout(flex, constraints: viewport);
expect(flexible.size.width, equals(0.0));
expect(flex.getMinIntrinsicHeight(viewport), equals(100.0));
expect(flex.getMaxIntrinsicHeight(viewport), equals(100.0));
expect(flex.getMinIntrinsicWidth(viewport), equals(100.0));
expect(flex.getMaxIntrinsicWidth(viewport), equals(100.0));
expect(flex.getMinIntrinsicHeight(100.0), equals(0.0));
expect(flex.getMaxIntrinsicHeight(100.0), equals(0.0));
expect(flex.getMinIntrinsicWidth(100.0), equals(200.0));
expect(flex.getMaxIntrinsicWidth(100.0), equals(200.0));
});
test('Vertical Flipped Constraints', () {
......@@ -72,7 +72,7 @@ void main() {
);
BoxConstraints viewport = new BoxConstraints(maxHeight: 200.0, maxWidth: 1000.0);
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
......
......@@ -7,29 +7,30 @@ import 'package:test/test.dart';
import 'rendering_tester.dart';
// before using this, consider using RenderSizedBox from rendering_tester.dart
class RenderTestBox extends RenderBox {
RenderTestBox(this._intrinsicDimensions);
final BoxConstraints _intrinsicDimensions;
@override
double getMinIntrinsicWidth(BoxConstraints constraints) {
return constraints.constrainWidth(_intrinsicDimensions.minWidth);
double getMinIntrinsicWidth(double height) {
return _intrinsicDimensions.minWidth;
}
@override
double getMaxIntrinsicWidth(BoxConstraints constraints) {
return constraints.constrainWidth(_intrinsicDimensions.maxWidth);
double getMaxIntrinsicWidth(double height) {
return _intrinsicDimensions.maxWidth;
}
@override
double getMinIntrinsicHeight(BoxConstraints constraints) {
return constraints.constrainHeight(_intrinsicDimensions.minHeight);
double getMinIntrinsicHeight(double width) {
return _intrinsicDimensions.minHeight;
}
@override
double getMaxIntrinsicHeight(BoxConstraints constraints) {
return constraints.constrainHeight(_intrinsicDimensions.maxHeight);
double getMaxIntrinsicHeight(double width) {
return _intrinsicDimensions.maxHeight;
}
@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 {
final Size _size;
@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);
}
@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