Cache intrinsic dimensions (#4446)
Also, make sure that the parent is notified when they change. Fixes #2298
This commit is contained in:
parent
6c896dcc70
commit
007d0a2f39
@ -454,28 +454,28 @@ class RenderBoxToRenderSectorAdapter extends RenderBox with RenderObjectWithChil
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
return getIntrinsicDimensions(height: height).width;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
return getIntrinsicDimensions(height: height).width;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
return getIntrinsicDimensions(width: width).height;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
return getIntrinsicDimensions(width: width).height;
|
||||
|
@ -14,22 +14,22 @@ class RenderSolidColorBox extends RenderDecoratedBox {
|
||||
super(decoration: new BoxDecoration(backgroundColor: backgroundColor));
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
return desiredSize.width == double.INFINITY ? 0.0 : desiredSize.width;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
return desiredSize.width == double.INFINITY ? 0.0 : desiredSize.width;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return desiredSize.height == double.INFINITY ? 0.0 : desiredSize.height;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return desiredSize.height == double.INFINITY ? 0.0 : desiredSize.height;
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ class _RenderTabBar extends RenderBox with
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
double maxWidth = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
while (child != null) {
|
||||
@ -112,7 +112,7 @@ class _RenderTabBar extends RenderBox with
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
double maxWidth = 0.0;
|
||||
double totalWidth = 0.0;
|
||||
RenderBox child = firstChild;
|
||||
@ -130,10 +130,10 @@ class _RenderTabBar extends RenderBox with
|
||||
double get _tabBarHeight => _tabHeight + _kTabIndicatorHeight;
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) => _tabBarHeight;
|
||||
double computeMinIntrinsicHeight(double width) => _tabBarHeight;
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) => _tabBarHeight;
|
||||
double computeMaxIntrinsicHeight(double width) => _tabBarHeight;
|
||||
|
||||
void layoutFixedWidthTabs() {
|
||||
double tabWidth = size.width / childCount;
|
||||
|
@ -180,7 +180,7 @@ class RenderBlock extends RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
switch (mainAxis) {
|
||||
case Axis.horizontal:
|
||||
return _getIntrinsicMainAxis((RenderBox child) => child.getMinIntrinsicWidth(height));
|
||||
@ -190,7 +190,7 @@ class RenderBlock extends RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
switch (mainAxis) {
|
||||
case Axis.horizontal:
|
||||
return _getIntrinsicMainAxis((RenderBox child) => child.getMaxIntrinsicWidth(height));
|
||||
@ -200,7 +200,7 @@ class RenderBlock extends RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
switch (mainAxis) {
|
||||
case Axis.horizontal:
|
||||
return _getIntrinsicMainAxis((RenderBox child) => child.getMinIntrinsicHeight(width));
|
||||
@ -210,7 +210,7 @@ class RenderBlock extends RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
switch (mainAxis) {
|
||||
case Axis.horizontal:
|
||||
return _getIntrinsicMainAxis((RenderBox child) => child.getMaxIntrinsicHeight(width));
|
||||
|
@ -471,6 +471,26 @@ class BoxParentData extends ParentData {
|
||||
/// ContainerRenderObjectMixin.
|
||||
abstract class ContainerBoxParentDataMixin<ChildType extends RenderObject> extends BoxParentData with ContainerParentDataMixin<ChildType> { }
|
||||
|
||||
enum _IntrinsicDimension { minWidth, maxWidth, minHeight, maxHeight }
|
||||
class _IntrinsicDimensionsCacheEntry {
|
||||
_IntrinsicDimensionsCacheEntry(this.dimension, this.argument);
|
||||
|
||||
final _IntrinsicDimension dimension;
|
||||
final double argument;
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
if (other is! _IntrinsicDimensionsCacheEntry)
|
||||
return false;
|
||||
final _IntrinsicDimensionsCacheEntry typedOther = other;
|
||||
return dimension == typedOther.dimension &&
|
||||
argument == typedOther.argument;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(dimension, argument);
|
||||
}
|
||||
|
||||
/// A render object in a 2D cartesian coordinate system.
|
||||
///
|
||||
/// The size of each box is expressed as a width and a height. Each box has its
|
||||
@ -496,6 +516,28 @@ abstract class RenderBox extends RenderObject {
|
||||
child.parentData = new BoxParentData();
|
||||
}
|
||||
|
||||
Map<_IntrinsicDimensionsCacheEntry, double> _cachedIntrinsicDimensions;
|
||||
|
||||
double _computeIntrinsicDimension(_IntrinsicDimension dimension, double argument, double computer(double argument)) {
|
||||
assert(RenderObject.debugCheckingIntrinsics || !debugDoingThisResize); // performResize should not depend on anything except the incoming constraints
|
||||
bool shouldCache = true;
|
||||
assert(() {
|
||||
// we don't want the checked-mode intrinsic tests to affect
|
||||
// who gets marked dirty, etc.
|
||||
if (RenderObject.debugCheckingIntrinsics)
|
||||
shouldCache = false;
|
||||
return true;
|
||||
});
|
||||
if (shouldCache) {
|
||||
_cachedIntrinsicDimensions ??= <_IntrinsicDimensionsCacheEntry, double>{};
|
||||
return _cachedIntrinsicDimensions.putIfAbsent(
|
||||
new _IntrinsicDimensionsCacheEntry(dimension, argument),
|
||||
() => computer(argument)
|
||||
);
|
||||
}
|
||||
return computer(argument);
|
||||
}
|
||||
|
||||
/// Returns the minimum width that this box could be without failing to
|
||||
/// correctly paint its contents within itself, without clipping.
|
||||
///
|
||||
@ -504,7 +546,25 @@ abstract class RenderBox extends RenderObject {
|
||||
/// environment is being requested. The given height should never be negative
|
||||
/// or null.
|
||||
///
|
||||
/// Override in subclasses that implement [performLayout].
|
||||
/// This function should only be called on one's children. Calling this
|
||||
/// function couples the child with the parent so that when the child's layout
|
||||
/// changes, the parent is notified (via [markNeedsLayout]).
|
||||
///
|
||||
/// Calling this function is expensive and as it can result in O(N^2)
|
||||
/// behavior.
|
||||
///
|
||||
/// Do not override this function. Instead, implement [computeMinIntrinsicWidth].
|
||||
@mustCallSuper
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
return _computeIntrinsicDimension(_IntrinsicDimension.minWidth, height, computeMinIntrinsicWidth);
|
||||
}
|
||||
|
||||
/// Computes the value returned by [getMinIntrinsicWidth]. Do not call this
|
||||
/// function directly, instead, call [getMinIntrinsicWidth].
|
||||
///
|
||||
/// Override in subclasses that implement [performLayout]. This method should
|
||||
/// return the minimum width that this box could be without failing to
|
||||
/// correctly paint its contents within itself, without clipping.
|
||||
///
|
||||
/// If the layout algorithm is independent of the context (e.g. it always
|
||||
/// tries to be a particular size), or if the layout algorithm is
|
||||
@ -516,6 +576,10 @@ abstract class RenderBox extends RenderObject {
|
||||
/// height-in-width-out when the width is unconstrained, then the height
|
||||
/// argument is the height to use.
|
||||
///
|
||||
/// If this algorithm depends on the intrinsic dimensions of a child, the
|
||||
/// intrinsic dimensions of that child should be obtained using the functions
|
||||
/// whose names start with `get`, not `compute`.
|
||||
///
|
||||
/// This function should never return a negative or infinite value.
|
||||
///
|
||||
/// ## Examples
|
||||
@ -526,14 +590,14 @@ abstract class RenderBox extends RenderObject {
|
||||
/// `height` argument is therefore ignored.
|
||||
///
|
||||
/// Consider the string "Hello World" The _maximum_ intrinsic width (as
|
||||
/// returned from [getMaxIntrinsicWidth]) would be the width of the string
|
||||
/// returned from [computeMaxIntrinsicWidth]) would be the width of the string
|
||||
/// with no line breaks.
|
||||
///
|
||||
/// The minimum intrinsic width would be the width of the widest word, "Hello"
|
||||
/// or "World". If the text is rendered in an even narrower width, however, it
|
||||
/// might still not overflow. For example, maybe the rendering would put a
|
||||
/// line-break half-way through the words, as in "Hel⁞lo⁞Wor⁞ld". However,
|
||||
/// this wouldn't be a _correct_ rendering, and [getMinIntrinsicWidth] is
|
||||
/// this wouldn't be a _correct_ rendering, and [computeMinIntrinsicWidth] is
|
||||
/// supposed to render the minimum width that the box could be without failing
|
||||
/// to _correctly_ paint the contents within itself.
|
||||
///
|
||||
@ -567,13 +631,14 @@ abstract class RenderBox extends RenderObject {
|
||||
/// incoming `height` or `width` argument is finite, treating that as a tight
|
||||
/// constraint in the respective direction and treating the other direction's
|
||||
/// constraints as unbounded. This is because the definitions of
|
||||
/// [getMinIntrinsicWidth] and [getMinIntrinsicHeight] are in terms of what
|
||||
/// the dimensions _could be_, and such boxes can only be one size in such
|
||||
/// cases.
|
||||
/// [computeMinIntrinsicWidth] and [computeMinIntrinsicHeight] are in terms of
|
||||
/// what the dimensions _could be_, and such boxes can only be one size in
|
||||
/// such cases.
|
||||
///
|
||||
/// When the incoming argument is not finite, then they should return the
|
||||
/// actual intrinsic dimensions based on the contents, as any other box would.
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
@protected
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@ -581,25 +646,50 @@ abstract class RenderBox extends RenderObject {
|
||||
/// decreases the preferred height. The preferred height is the value that
|
||||
/// would be returned by [getMinIntrinsicHeight] for that width.
|
||||
///
|
||||
/// Override in subclasses that implement [performLayout].
|
||||
/// This function should only be called on one's children. Calling this
|
||||
/// function couples the child with the parent so that when the child's layout
|
||||
/// changes, the parent is notified (via [markNeedsLayout]).
|
||||
///
|
||||
/// Calling this function is expensive and as it can result in O(N^2)
|
||||
/// behavior.
|
||||
///
|
||||
/// Do not override this function. Instead, implement
|
||||
/// [computeMaxIntrinsicWidth].
|
||||
@mustCallSuper
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
return _computeIntrinsicDimension(_IntrinsicDimension.maxWidth, height, computeMaxIntrinsicWidth);
|
||||
}
|
||||
|
||||
/// Computes the value returned by [getMaxIntrinsicWidth]. Do not call this
|
||||
/// function directly, instead, call [getMaxIntrinsicWidth].
|
||||
///
|
||||
/// Override in subclasses that implement [performLayout]. This should return
|
||||
/// the smallest width beyond which increasing the width never decreases the
|
||||
/// preferred height. The preferred height is the value that would be returned
|
||||
/// by [computeMinIntrinsicHeight] for that width.
|
||||
///
|
||||
/// If the layout algorithm is strictly height-in-width-out, or is
|
||||
/// height-in-width-out when the width is unconstrained, then this should
|
||||
/// return the same value as [getMinIntrinsicWidth] for the same height.
|
||||
/// return the same value as [computeMinIntrinsicWidth] for the same height.
|
||||
///
|
||||
/// Otherwise, the height argument should be ignored, and the returned value
|
||||
/// should be equal to or bigger than the value returned by
|
||||
/// [getMinIntrinsicWidth].
|
||||
/// [computeMinIntrinsicWidth].
|
||||
///
|
||||
/// The value returned by this method might not match the size that the object
|
||||
/// would actually take. For example, a [RenderBox] subclass that always
|
||||
/// exactly sizes itself using [BoxConstraints.biggest] might well size itself
|
||||
/// bigger than its max intrinsic size.
|
||||
///
|
||||
/// If this algorithm depends on the intrinsic dimensions of a child, the
|
||||
/// intrinsic dimensions of that child should be obtained using the functions
|
||||
/// whose names start with `get`, not `compute`.
|
||||
///
|
||||
/// This function should never return a negative or infinite value.
|
||||
///
|
||||
/// See also examples in the definition of [getMinIntrinsicWidth].
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
/// See also examples in the definition of [computeMinIntrinsicWidth].
|
||||
@protected
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@ -611,7 +701,26 @@ abstract class RenderBox extends RenderObject {
|
||||
/// environment is being requested. The given width should never be negative
|
||||
/// or null.
|
||||
///
|
||||
/// Override in subclasses that implement [performLayout].
|
||||
/// This function should only be called on one's children. Calling this
|
||||
/// function couples the child with the parent so that when the child's layout
|
||||
/// changes, the parent is notified (via [markNeedsLayout]).
|
||||
///
|
||||
/// Calling this function is expensive and as it can result in O(N^2)
|
||||
/// behavior.
|
||||
///
|
||||
/// Do not override this function. Instead, implement
|
||||
/// [computeMinIntrinsicHeight].
|
||||
@mustCallSuper
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
return _computeIntrinsicDimension(_IntrinsicDimension.minHeight, width, computeMinIntrinsicHeight);
|
||||
}
|
||||
|
||||
/// Computes the value returned by [getMinIntrinsicHeight]. Do not call this
|
||||
/// function directly, instead, call [getMinIntrinsicHeight].
|
||||
///
|
||||
/// Override in subclasses that implement [performLayout]. Should return the
|
||||
/// minimum height that this box could be without failing to correctly paint
|
||||
/// its contents within itself, without clipping.
|
||||
///
|
||||
/// If the layout algorithm is independent of the context (e.g. it always
|
||||
/// tries to be a particular size), or if the layout algorithm is
|
||||
@ -623,10 +732,15 @@ abstract class RenderBox extends RenderObject {
|
||||
/// width-in-height-out when the height is unconstrained, then the width
|
||||
/// argument is the width to use.
|
||||
///
|
||||
/// If this algorithm depends on the intrinsic dimensions of a child, the
|
||||
/// intrinsic dimensions of that child should be obtained using the functions
|
||||
/// whose names start with `get`, not `compute`.
|
||||
///
|
||||
/// This function should never return a negative or infinite value.
|
||||
///
|
||||
/// See also examples in the definition of [getMinIntrinsicWidth].
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
/// See also examples in the definition of [computeMinIntrinsicWidth].
|
||||
@protected
|
||||
double computeMinIntrinsicHeight(double height) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@ -634,25 +748,50 @@ abstract class RenderBox extends RenderObject {
|
||||
/// decreases the preferred width. The preferred width is the value that
|
||||
/// would be returned by [getMinIntrinsicWidth] for that height.
|
||||
///
|
||||
/// Override in subclasses that implement [performLayout].
|
||||
/// This function should only be called on one's children. Calling this
|
||||
/// function couples the child with the parent so that when the child's layout
|
||||
/// changes, the parent is notified (via [markNeedsLayout]).
|
||||
///
|
||||
/// Calling this function is expensive and as it can result in O(N^2)
|
||||
/// behavior.
|
||||
///
|
||||
/// Do not override this function. Instead, implement
|
||||
/// [computeMaxIntrinsicHeight].
|
||||
@mustCallSuper
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
return _computeIntrinsicDimension(_IntrinsicDimension.maxHeight, width, computeMaxIntrinsicHeight);
|
||||
}
|
||||
|
||||
/// Computes the value returned by [getMaxIntrinsicHeight]. Do not call this
|
||||
/// function directly, instead, call [getMaxIntrinsicHeight].
|
||||
///
|
||||
/// Override in subclasses that implement [performLayout]. Should return the
|
||||
/// smallest height beyond which increasing the height never decreases the
|
||||
/// preferred width. The preferred width is the value that would be returned
|
||||
/// by [computeMinIntrinsicWidth] for that height.
|
||||
///
|
||||
/// If the layout algorithm is strictly width-in-height-out, or is
|
||||
/// width-in-height-out when the height is unconstrained, then this should
|
||||
/// return the same value as [getMinIntrinsicHeight] for the same width.
|
||||
/// return the same value as [computeMinIntrinsicHeight] for the same width.
|
||||
///
|
||||
/// Otherwise, the width argument should be ignored, and the returned value
|
||||
/// should be equal to or bigger than the value returned by
|
||||
/// [getMinIntrinsicHeight].
|
||||
/// [computeMinIntrinsicHeight].
|
||||
///
|
||||
/// The value returned by this method might not match the size that the object
|
||||
/// would actually take. For example, a [RenderBox] subclass that always
|
||||
/// exactly sizes itself using [BoxConstraints.biggest] might well size itself
|
||||
/// bigger than its max intrinsic size.
|
||||
///
|
||||
/// If this algorithm depends on the intrinsic dimensions of a child, the
|
||||
/// intrinsic dimensions of that child should be obtained using the functions
|
||||
/// whose names start with `get`, not `compute`.
|
||||
///
|
||||
/// This function should never return a negative or infinite value.
|
||||
///
|
||||
/// See also examples in the definition of [getMinIntrinsicWidth].
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
/// See also examples in the definition of [computeMinIntrinsicWidth].
|
||||
@protected
|
||||
double computeMaxIntrinsicHeight(double height) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@ -749,7 +888,6 @@ abstract class RenderBox extends RenderObject {
|
||||
}
|
||||
|
||||
Map<TextBaseline, double> _cachedBaselines;
|
||||
bool _ancestorUsesBaseline = false;
|
||||
static bool _debugDoingBaseline = false;
|
||||
static bool _debugSetDoingBaseline(bool value) {
|
||||
_debugDoingBaseline = value;
|
||||
@ -795,9 +933,9 @@ abstract class RenderBox extends RenderObject {
|
||||
/// This function must only be called from [getDistanceToBaseline] and
|
||||
/// [computeDistanceToActualBaseline]. Do not call this function directly from
|
||||
/// outside those two methods.
|
||||
@mustCallSuper
|
||||
double getDistanceToActualBaseline(TextBaseline baseline) {
|
||||
assert(_debugDoingBaseline);
|
||||
_ancestorUsesBaseline = true;
|
||||
if (_cachedBaselines == null)
|
||||
_cachedBaselines = new Map<TextBaseline, double>();
|
||||
_cachedBaselines.putIfAbsent(baseline, () => computeDistanceToActualBaseline(baseline));
|
||||
@ -953,20 +1091,19 @@ abstract class RenderBox extends RenderObject {
|
||||
|
||||
@override
|
||||
void markNeedsLayout() {
|
||||
if (_cachedBaselines != null && _cachedBaselines.isNotEmpty) {
|
||||
// if we have cached data, then someone must have used our data
|
||||
assert(_ancestorUsesBaseline);
|
||||
final RenderObject parent = this.parent;
|
||||
parent?.markNeedsLayout();
|
||||
assert(parent == this.parent);
|
||||
// Now that they're dirty, we can forget that they used the
|
||||
// baseline. If they use it again, then we'll set the bit
|
||||
// again, and if we get dirty again, we'll notify them again.
|
||||
_ancestorUsesBaseline = false;
|
||||
_cachedBaselines.clear();
|
||||
} else {
|
||||
// if we've never cached any data, then nobody can have used it
|
||||
assert(!_ancestorUsesBaseline);
|
||||
if ((_cachedBaselines != null && _cachedBaselines.isNotEmpty) ||
|
||||
(_cachedIntrinsicDimensions != null && _cachedIntrinsicDimensions.isNotEmpty)) {
|
||||
// If we have cached data, then someone must have used our data.
|
||||
// Since the parent will shortly be marked dirty, we can forget that they
|
||||
// used the baseline and/or intrinsic dimensions. If they use them again,
|
||||
// then we'll fill the cache again, and if we get dirty again, we'll
|
||||
// notify them again.
|
||||
_cachedBaselines?.clear();
|
||||
_cachedIntrinsicDimensions?.clear();
|
||||
if (parent is RenderObject) {
|
||||
markParentNeedsLayout();
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.markNeedsLayout();
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
|
||||
// or we should expose intrinsic delegate callbacks and throw if they're not implemented.
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
|
||||
if (width.isFinite)
|
||||
return width;
|
||||
@ -252,7 +252,7 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
|
||||
if (width.isFinite)
|
||||
return width;
|
||||
@ -260,7 +260,7 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
|
||||
if (height.isFinite)
|
||||
return height;
|
||||
@ -268,7 +268,7 @@ class RenderCustomMultiChildLayoutBox extends RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
|
||||
if (height.isFinite)
|
||||
return height;
|
||||
|
@ -61,6 +61,11 @@ double debugRepaintRainbowHueIncrement = 2.0;
|
||||
bool debugPrintMarkNeedsPaintStacks = false;
|
||||
|
||||
/// Log the call stacks that mark render objects as needing layout.
|
||||
///
|
||||
/// For sanity, this only logs the stack traces of cases where an object is
|
||||
/// added to the list of nodes needing layout. This avoids printing multiple
|
||||
/// redundant stack traces as a single [RenderObject.markNeedsLayout] call walks
|
||||
/// up the tree.
|
||||
bool debugPrintMarkNeedsLayoutStacks = false;
|
||||
|
||||
/// Check the intrinsic sizes of each [RenderBox] during layout.
|
||||
|
@ -192,12 +192,12 @@ class RenderEditableLine extends RenderBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return _preferredHeight;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return _preferredHeight;
|
||||
}
|
||||
|
||||
|
@ -54,12 +54,12 @@ class RenderErrorBox extends RenderBox {
|
||||
ui.Paragraph _paragraph;
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
return _kMaxWidth;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return _kMaxHeight;
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
return _getIntrinsicSize(
|
||||
sizingDirection: FlexDirection.horizontal,
|
||||
extent: height,
|
||||
@ -247,7 +247,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
return _getIntrinsicSize(
|
||||
sizingDirection: FlexDirection.horizontal,
|
||||
extent: height,
|
||||
@ -256,7 +256,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return _getIntrinsicSize(
|
||||
sizingDirection: FlexDirection.vertical,
|
||||
extent: width,
|
||||
@ -265,7 +265,7 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return _getIntrinsicSize(
|
||||
sizingDirection: FlexDirection.vertical,
|
||||
extent: width,
|
||||
|
@ -245,7 +245,7 @@ class RenderFlow extends RenderBox
|
||||
// or we should expose intrinsic delegate callbacks and throw if they're not implemented.
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
|
||||
if (width.isFinite)
|
||||
return width;
|
||||
@ -253,7 +253,7 @@ class RenderFlow extends RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
|
||||
if (width.isFinite)
|
||||
return width;
|
||||
@ -261,7 +261,7 @@ class RenderFlow extends RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
|
||||
if (height.isFinite)
|
||||
return height;
|
||||
@ -269,7 +269,7 @@ class RenderFlow extends RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
|
||||
if (height.isFinite)
|
||||
return height;
|
||||
|
@ -212,11 +212,12 @@ abstract class GridDelegate {
|
||||
/// Returns the minimum width that this grid could be without failing to paint
|
||||
/// its contents within itself.
|
||||
///
|
||||
/// Override this to provide a more efficient solution. The default
|
||||
/// implementation actually instantiates a grid specification and measures the
|
||||
/// grid at the given height and child count.
|
||||
/// Override this to provide a more efficient or more correct solution. The
|
||||
/// default implementation actually instantiates a grid specification and
|
||||
/// measures the grid at the given height and child count.
|
||||
///
|
||||
/// For more details, see [RenderBox.getMinIntrinsicWidth].
|
||||
/// For more details on implementing this method, see
|
||||
/// [RenderBox.computeMinIntrinsicWidth].
|
||||
double getMinIntrinsicWidth(double height, int childCount) {
|
||||
final double width = _getGridSize(new BoxConstraints.tightForFinite(height: height), childCount).width;
|
||||
if (width.isFinite)
|
||||
@ -227,11 +228,12 @@ abstract class GridDelegate {
|
||||
/// Returns the smallest width beyond which increasing the width never
|
||||
/// decreases the preferred height.
|
||||
///
|
||||
/// Override this to provide a more efficient solution. The default
|
||||
/// implementation actually instantiates a grid specification and measures the
|
||||
/// grid at the given height and child count.
|
||||
/// Override this to provide a more efficient or more correct solution. The
|
||||
/// default implementation actually instantiates a grid specification and
|
||||
/// measures the grid at the given height and child count.
|
||||
///
|
||||
/// For more details, see [RenderBox.getMaxIntrinsicWidth].
|
||||
/// For more details on implementing this method, see
|
||||
/// [RenderBox.computeMaxIntrinsicWidth].
|
||||
double getMaxIntrinsicWidth(double height, int childCount) {
|
||||
final double width = _getGridSize(new BoxConstraints.tightForFinite(height: height), childCount).width;
|
||||
if (width.isFinite)
|
||||
@ -242,11 +244,12 @@ abstract class GridDelegate {
|
||||
/// Return the minimum height that this grid could be without failing to paint
|
||||
/// its contents within itself.
|
||||
///
|
||||
/// Override this to provide a more efficient solution. The default
|
||||
/// implementation actually instantiates a grid specification and measures the
|
||||
/// grid at the given width and child count.
|
||||
/// Override this to provide a more efficient or more correct solution. The
|
||||
/// default implementation actually instantiates a grid specification and
|
||||
/// measures the grid at the given height and child count.
|
||||
///
|
||||
/// For more details, see [RenderBox.getMinIntrinsicHeight].
|
||||
/// For more details on implementing this method, see
|
||||
/// [RenderBox.computeMinIntrinsicHeight].
|
||||
double getMinIntrinsicHeight(double width, int childCount) {
|
||||
final double height = _getGridSize(new BoxConstraints.tightForFinite(width: width), childCount).height;
|
||||
if (height.isFinite)
|
||||
@ -257,11 +260,12 @@ abstract class GridDelegate {
|
||||
/// Returns the smallest height beyond which increasing the height never
|
||||
/// decreases the preferred width.
|
||||
///
|
||||
/// Override this to provide a more efficient solution. The default
|
||||
/// implementation actually instantiates a grid specification and measures the
|
||||
/// grid at the given width and child count.
|
||||
/// Override this to provide a more efficient or more correct solution. The
|
||||
/// default implementation actually instantiates a grid specification and
|
||||
/// measures the grid at the given height and child count.
|
||||
///
|
||||
/// For more details, see [RenderBox.getMaxIntrinsicHeight].
|
||||
/// For more details on implementing this method, see
|
||||
/// [RenderBox.computeMaxIntrinsicHeight].
|
||||
double getMaxIntrinsicHeight(double width, int childCount) {
|
||||
final double height = _getGridSize(new BoxConstraints.tightForFinite(width: width), childCount).height;
|
||||
if (height.isFinite)
|
||||
@ -581,22 +585,22 @@ class RenderGrid extends RenderVirtualViewport<GridParentData> {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
return _delegate.getMinIntrinsicWidth(height, virtualChildCount);
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
return _delegate.getMaxIntrinsicWidth(height, virtualChildCount);
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return _delegate.getMinIntrinsicHeight(width, virtualChildCount);
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return _delegate.getMaxIntrinsicHeight(width, virtualChildCount);
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,7 @@ class RenderImage extends RenderBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
assert(height >= 0.0);
|
||||
if (_width == null && _height == null)
|
||||
return 0.0;
|
||||
@ -213,13 +213,13 @@ class RenderImage extends RenderBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
assert(height >= 0.0);
|
||||
return _sizeForConstraints(new BoxConstraints.tightForFinite(height: height)).width;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
assert(width >= 0.0);
|
||||
if (_width == null && _height == null)
|
||||
return 0.0;
|
||||
@ -227,7 +227,7 @@ class RenderImage extends RenderBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
assert(width >= 0.0);
|
||||
return _sizeForConstraints(new BoxConstraints.tightForFinite(width: width)).height;
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ class RenderList extends RenderVirtualViewport<ListParentData> {
|
||||
return extent;
|
||||
}
|
||||
|
||||
double _getIntrinsicWidth() {
|
||||
double _computeIntrinsicWidth() {
|
||||
switch (mainAxis) {
|
||||
case Axis.vertical:
|
||||
assert(debugThrowIfNotCheckingIntrinsics());
|
||||
@ -111,16 +111,16 @@ class RenderList extends RenderVirtualViewport<ListParentData> {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
return _getIntrinsicWidth();
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
return _computeIntrinsicWidth();
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
return _getIntrinsicWidth();
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
return _computeIntrinsicWidth();
|
||||
}
|
||||
|
||||
double _getIntrinsicHeight() {
|
||||
double _computeIntrinsicHeight() {
|
||||
switch (mainAxis) {
|
||||
case Axis.vertical:
|
||||
final double height = _preferredExtent;
|
||||
@ -135,13 +135,13 @@ class RenderList extends RenderVirtualViewport<ListParentData> {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
return _getIntrinsicHeight();
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return _computeIntrinsicHeight();
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
return _getIntrinsicHeight();
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return _computeIntrinsicHeight();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -1199,7 +1199,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
||||
/// debugAssertDoesMeetConstraints(), and should not be checked in
|
||||
/// release mode (where it will always be false).
|
||||
static bool debugCheckingIntrinsics = false;
|
||||
bool _debugAncestorsAlreadyMarkedNeedsLayout() {
|
||||
bool _debugSubtreeRelayoutRootAlreadyMarkedNeedsLayout() {
|
||||
if (_relayoutSubtreeRoot == null)
|
||||
return true; // we haven't yet done layout even once, so there's nothing for us to do
|
||||
RenderObject node = this;
|
||||
@ -1214,49 +1214,83 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Mark this render object's layout information as dirty.
|
||||
/// Mark this render object's layout information as dirty, and either register
|
||||
/// this object with its [PipelineOwner], or defer to the parent, depending on
|
||||
/// whether this object is a relayout boundary or not respectively.
|
||||
///
|
||||
/// ## Background
|
||||
///
|
||||
/// Rather than eagerly updating layout information in response to writes into
|
||||
/// this render object, we instead mark the layout information as dirty, which
|
||||
/// a render object, we instead mark the layout information as dirty, which
|
||||
/// schedules a visual update. As part of the visual update, the rendering
|
||||
/// pipeline will update this render object's layout information.
|
||||
/// pipeline updates the render object's layout information.
|
||||
///
|
||||
/// This mechanism batches the layout work so that multiple sequential writes
|
||||
/// are coalesced, removing redundant computation.
|
||||
///
|
||||
/// Causes [needsLayout] to return true for this render object. If the parent
|
||||
/// render object indicated that it uses the size of this render object in
|
||||
/// computing its layout information, this function will also mark the parent
|
||||
/// as needing layout.
|
||||
/// If a render object's parent indicates that it uses the size of one of its
|
||||
/// render object children when computing its layout information, this
|
||||
/// function, when called for the child, will also mark the parent as needing
|
||||
/// layout. In that case, since both the parent and the child need to have
|
||||
/// their layout recomputed, the pipeline owner is only notified about the
|
||||
/// parent; when the parent is laid out, it will call the child's [layout]
|
||||
/// method and thus the child will be laid out as well.
|
||||
///
|
||||
/// Once [markNeedsLayout] has been called on a render object, [needsLayout]
|
||||
/// returns true for that render object until just after the pipeline owner
|
||||
/// has called [layout] on the render object.
|
||||
///
|
||||
/// ## Special cases
|
||||
///
|
||||
/// Some subclasses of [RenderObject], notably [RenderBox], have other
|
||||
/// situations in which the parent needs to be notified if the child is
|
||||
/// dirtied. Such subclasses override markNeedsLayout and either call
|
||||
/// `super.markNeedsLayout()`, in the normal case, or call
|
||||
/// [markParentNeedsLayout], in the case where the parent neds to be laid out
|
||||
/// as well as the child.
|
||||
void markNeedsLayout() {
|
||||
assert(_debugCanPerformMutations);
|
||||
if (_needsLayout) {
|
||||
assert(_debugAncestorsAlreadyMarkedNeedsLayout());
|
||||
assert(_debugSubtreeRelayoutRootAlreadyMarkedNeedsLayout());
|
||||
return;
|
||||
}
|
||||
_needsLayout = true;
|
||||
assert(_relayoutSubtreeRoot != null);
|
||||
if (_relayoutSubtreeRoot != this) {
|
||||
final RenderObject parent = this.parent;
|
||||
if (!_doingThisLayoutWithCallback) {
|
||||
parent.markNeedsLayout();
|
||||
} else {
|
||||
assert(parent._debugDoingThisLayout);
|
||||
}
|
||||
assert(parent == this.parent);
|
||||
markParentNeedsLayout();
|
||||
} else {
|
||||
assert(() {
|
||||
if (debugPrintMarkNeedsLayoutStacks)
|
||||
debugPrintStack();
|
||||
return true;
|
||||
});
|
||||
_needsLayout = true;
|
||||
if (owner != null) {
|
||||
assert(() {
|
||||
if (debugPrintMarkNeedsLayoutStacks)
|
||||
debugPrintStack();
|
||||
return true;
|
||||
});
|
||||
owner._nodesNeedingLayout.add(this);
|
||||
owner.requestVisualUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark this render object's layout information as dirty, and then defer to
|
||||
/// the parent.
|
||||
///
|
||||
/// This function should only be called from [markNeedsLayout] implementations
|
||||
/// of subclasses that introduce more reasons for deferring the handling of
|
||||
/// dirty layout to the parent. See [markNeedsLayout] for details.
|
||||
///
|
||||
/// Only call this if [parent] is not null.
|
||||
@protected
|
||||
void markParentNeedsLayout() {
|
||||
_needsLayout = true;
|
||||
final RenderObject parent = this.parent;
|
||||
if (!_doingThisLayoutWithCallback) {
|
||||
parent.markNeedsLayout();
|
||||
} else {
|
||||
assert(parent._debugDoingThisLayout);
|
||||
}
|
||||
assert(parent == this.parent);
|
||||
}
|
||||
|
||||
void _cleanRelayoutSubtreeRoot() {
|
||||
if (_relayoutSubtreeRoot != this) {
|
||||
_relayoutSubtreeRoot = null;
|
||||
|
@ -92,30 +92,30 @@ class RenderParagraph extends RenderBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
_layoutText();
|
||||
return _textPainter.minIntrinsicWidth;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
_layoutText();
|
||||
return _textPainter.maxIntrinsicWidth;
|
||||
}
|
||||
|
||||
double _getIntrinsicHeight(double width) {
|
||||
double _computeIntrinsicHeight(double width) {
|
||||
_layoutText(minWidth: width, maxWidth: width);
|
||||
return _textPainter.height;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
return _getIntrinsicHeight(width);
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return _computeIntrinsicHeight(width);
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
return _getIntrinsicHeight(width);
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return _computeIntrinsicHeight(width);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -97,12 +97,12 @@ class RenderPerformanceOverlay extends RenderBox {
|
||||
bool get alwaysNeedsCompositing => true;
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@ -119,12 +119,12 @@ class RenderPerformanceOverlay extends RenderBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return _intrinsicHeight;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return _intrinsicHeight;
|
||||
}
|
||||
|
||||
|
@ -42,28 +42,28 @@ class RenderProxyBox extends RenderBox with RenderObjectWithChildMixin<RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
if (child != null)
|
||||
return child.getMinIntrinsicWidth(height);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
if (child != null)
|
||||
return child.getMaxIntrinsicWidth(height);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
if (child != null)
|
||||
return child.getMinIntrinsicHeight(width);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
if (child != null)
|
||||
return child.getMaxIntrinsicHeight(width);
|
||||
return 0.0;
|
||||
@ -195,32 +195,32 @@ class RenderConstrainedBox extends RenderProxyBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
final double width = super.getMinIntrinsicWidth(height);
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
final double width = super.computeMinIntrinsicWidth(height);
|
||||
if (_additionalConstraints.hasBoundedWidth)
|
||||
return _additionalConstraints.constrainWidth(width);
|
||||
return width;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
final double width = super.getMaxIntrinsicWidth(height);
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
final double width = super.computeMaxIntrinsicWidth(height);
|
||||
if (_additionalConstraints.hasBoundedWidth)
|
||||
return _additionalConstraints.constrainWidth(width);
|
||||
return width;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
final double height = super.getMinIntrinsicHeight(width);
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
final double height = super.computeMinIntrinsicHeight(width);
|
||||
if (_additionalConstraints.hasBoundedHeight)
|
||||
return _additionalConstraints.constrainHeight(height);
|
||||
return height;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
final double height = super.getMaxIntrinsicHeight(width);
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
final double height = super.computeMaxIntrinsicHeight(width);
|
||||
if (_additionalConstraints.hasBoundedHeight)
|
||||
return _additionalConstraints.constrainHeight(height);
|
||||
return height;
|
||||
@ -381,7 +381,7 @@ class RenderAspectRatio extends RenderProxyBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
if (height.isFinite)
|
||||
return height * _aspectRatio;
|
||||
if (child != null)
|
||||
@ -390,7 +390,7 @@ class RenderAspectRatio extends RenderProxyBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
if (height.isFinite)
|
||||
return height * _aspectRatio;
|
||||
if (child != null)
|
||||
@ -399,7 +399,7 @@ class RenderAspectRatio extends RenderProxyBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
if (width.isFinite)
|
||||
return width / _aspectRatio;
|
||||
if (child != null)
|
||||
@ -408,7 +408,7 @@ class RenderAspectRatio extends RenderProxyBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
if (width.isFinite)
|
||||
return width / _aspectRatio;
|
||||
if (child != null)
|
||||
@ -537,12 +537,12 @@ class RenderIntrinsicWidth extends RenderProxyBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
return getMaxIntrinsicWidth(height);
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
return computeMaxIntrinsicWidth(height);
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
final double width = child.getMaxIntrinsicWidth(height);
|
||||
@ -550,22 +550,22 @@ class RenderIntrinsicWidth extends RenderProxyBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
if (!width.isFinite)
|
||||
width = getMaxIntrinsicWidth(double.INFINITY);
|
||||
width = computeMaxIntrinsicWidth(double.INFINITY);
|
||||
assert(width.isFinite);
|
||||
final double height = child.getMinIntrinsicHeight(width);
|
||||
return _applyStep(height, _stepHeight);
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
if (!width.isFinite)
|
||||
width = getMaxIntrinsicWidth(double.INFINITY);
|
||||
width = computeMaxIntrinsicWidth(double.INFINITY);
|
||||
assert(width.isFinite);
|
||||
final double height = child.getMaxIntrinsicHeight(width);
|
||||
return _applyStep(height, _stepHeight);
|
||||
@ -614,7 +614,7 @@ class RenderIntrinsicHeight extends RenderProxyBox {
|
||||
}) : super(child);
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
if (!height.isFinite)
|
||||
@ -624,7 +624,7 @@ class RenderIntrinsicHeight extends RenderProxyBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
if (!height.isFinite)
|
||||
@ -634,8 +634,8 @@ class RenderIntrinsicHeight extends RenderProxyBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
return getMaxIntrinsicHeight(width);
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return computeMaxIntrinsicHeight(width);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -43,28 +43,28 @@ class RenderRotatedBox extends RenderBox with RenderObjectWithChildMixin<RenderB
|
||||
bool get _isVertical => quarterTurns % 2 == 1;
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
return _isVertical ? child.getMinIntrinsicHeight(height) : child.getMinIntrinsicWidth(height);
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
return _isVertical ? child.getMaxIntrinsicHeight(height) : child.getMaxIntrinsicWidth(height);
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
return _isVertical ? child.getMinIntrinsicWidth(width) : child.getMinIntrinsicHeight(width);
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
if (child == null)
|
||||
return 0.0;
|
||||
return _isVertical ? child.getMaxIntrinsicWidth(width) : child.getMaxIntrinsicHeight(width);
|
||||
|
@ -17,28 +17,28 @@ abstract class RenderShiftedBox extends RenderBox with RenderObjectWithChildMixi
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
if (child != null)
|
||||
return child.getMinIntrinsicWidth(height);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
if (child != null)
|
||||
return child.getMaxIntrinsicWidth(height);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
if (child != null)
|
||||
return child.getMinIntrinsicHeight(width);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
if (child != null)
|
||||
return child.getMaxIntrinsicHeight(width);
|
||||
return 0.0;
|
||||
@ -111,7 +111,7 @@ class RenderPadding extends RenderShiftedBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
final double totalHorizontalPadding = padding.left + padding.right;
|
||||
final double totalVerticalPadding = padding.top + padding.bottom;
|
||||
if (child != null) // next line relies on double.INFINITY absorption
|
||||
@ -120,7 +120,7 @@ class RenderPadding extends RenderShiftedBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
final double totalHorizontalPadding = padding.left + padding.right;
|
||||
final double totalVerticalPadding = padding.top + padding.bottom;
|
||||
if (child != null) // next line relies on double.INFINITY absorption
|
||||
@ -129,7 +129,7 @@ class RenderPadding extends RenderShiftedBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
final double totalHorizontalPadding = padding.left + padding.right;
|
||||
final double totalVerticalPadding = padding.top + padding.bottom;
|
||||
if (child != null) // next line relies on double.INFINITY absorption
|
||||
@ -138,7 +138,7 @@ class RenderPadding extends RenderShiftedBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
final double totalHorizontalPadding = padding.left + padding.right;
|
||||
final double totalVerticalPadding = padding.top + padding.bottom;
|
||||
if (child != null) // next line relies on double.INFINITY absorption
|
||||
@ -551,22 +551,22 @@ class RenderSizedOverflowBox extends RenderAligningShiftedBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
return _requestedSize.width;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
return _requestedSize.width;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return _requestedSize.height;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return _requestedSize.height;
|
||||
}
|
||||
|
||||
@ -667,10 +667,10 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
double result;
|
||||
if (child == null) {
|
||||
result = super.getMinIntrinsicWidth(height);
|
||||
result = super.computeMinIntrinsicWidth(height);
|
||||
} else { // the following line relies on double.INFINITY absorption
|
||||
result = child.getMinIntrinsicWidth(height * (_heightFactor ?? 1.0));
|
||||
}
|
||||
@ -679,10 +679,10 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
double result;
|
||||
if (child == null) {
|
||||
result = super.getMaxIntrinsicWidth(height);
|
||||
result = super.computeMaxIntrinsicWidth(height);
|
||||
} else { // the following line relies on double.INFINITY absorption
|
||||
result = child.getMaxIntrinsicWidth(height * (_heightFactor ?? 1.0));
|
||||
}
|
||||
@ -691,10 +691,10 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
double result;
|
||||
if (child == null) {
|
||||
result = super.getMinIntrinsicHeight(width);
|
||||
result = super.computeMinIntrinsicHeight(width);
|
||||
} else { // the following line relies on double.INFINITY absorption
|
||||
result = child.getMinIntrinsicHeight(width * (_widthFactor ?? 1.0));
|
||||
}
|
||||
@ -703,10 +703,10 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
double result;
|
||||
if (child == null) {
|
||||
result = super.getMaxIntrinsicHeight(width);
|
||||
result = super.computeMaxIntrinsicHeight(width);
|
||||
} else { // the following line relies on double.INFINITY absorption
|
||||
result = child.getMaxIntrinsicHeight(width * (_widthFactor ?? 1.0));
|
||||
}
|
||||
@ -786,7 +786,7 @@ class RenderCustomSingleChildLayoutBox extends RenderShiftedBox {
|
||||
// or we should expose intrinsic delegate callbacks and throw if they're not implemented.
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
|
||||
if (width.isFinite)
|
||||
return width;
|
||||
@ -794,7 +794,7 @@ class RenderCustomSingleChildLayoutBox extends RenderShiftedBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
final double width = _getSize(new BoxConstraints.tightForFinite(height: height)).width;
|
||||
if (width.isFinite)
|
||||
return width;
|
||||
@ -802,7 +802,7 @@ class RenderCustomSingleChildLayoutBox extends RenderShiftedBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
|
||||
if (height.isFinite)
|
||||
return height;
|
||||
@ -810,7 +810,7 @@ class RenderCustomSingleChildLayoutBox extends RenderShiftedBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
final double height = _getSize(new BoxConstraints.tightForFinite(width: width)).height;
|
||||
if (height.isFinite)
|
||||
return height;
|
||||
|
@ -286,22 +286,22 @@ class RenderStack extends RenderBox
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
return _getIntrinsicDimension((RenderBox child) => child.getMinIntrinsicWidth(height));
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
return _getIntrinsicDimension((RenderBox child) => child.getMaxIntrinsicWidth(height));
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return _getIntrinsicDimension((RenderBox child) => child.getMinIntrinsicHeight(width));
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return _getIntrinsicDimension((RenderBox child) => child.getMaxIntrinsicHeight(width));
|
||||
}
|
||||
|
||||
|
@ -819,7 +819,7 @@ class RenderTable extends RenderBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
assert(_children.length == rows * columns);
|
||||
double totalMinWidth = 0.0;
|
||||
for (int x = 0; x < columns; x += 1) {
|
||||
@ -831,7 +831,7 @@ class RenderTable extends RenderBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
assert(_children.length == rows * columns);
|
||||
double totalMaxWidth = 0.0;
|
||||
for (int x = 0; x < columns; x += 1) {
|
||||
@ -843,7 +843,7 @@ class RenderTable extends RenderBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(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(_children.length == rows * columns);
|
||||
@ -863,8 +863,8 @@ class RenderTable extends RenderBox {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
return getMinIntrinsicHeight(width);
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return computeMinIntrinsicHeight(width);
|
||||
}
|
||||
|
||||
double _baselineDistance;
|
||||
|
@ -236,28 +236,28 @@ class RenderViewport extends RenderViewportBase with RenderObjectWithChildMixin<
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
if (child != null)
|
||||
return child.getMinIntrinsicWidth(height);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
if (child != null)
|
||||
return child.getMaxIntrinsicWidth(height);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
if (child != null)
|
||||
return child.getMinIntrinsicHeight(width);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
if (child != null)
|
||||
return child.getMaxIntrinsicHeight(width);
|
||||
return 0.0;
|
||||
@ -408,25 +408,25 @@ abstract class RenderVirtualViewport<T extends ContainerBoxParentDataMixin<Rende
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
assert(debugThrowIfNotCheckingIntrinsics());
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
assert(debugThrowIfNotCheckingIntrinsics());
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
assert(debugThrowIfNotCheckingIntrinsics());
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
assert(debugThrowIfNotCheckingIntrinsics());
|
||||
return 0.0;
|
||||
}
|
||||
|
@ -66,25 +66,25 @@ class _RenderLayoutBuilder extends RenderBox with RenderObjectWithChildMixin<Ren
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
assert(_debugThrowIfNotCheckingIntrinsics());
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
assert(_debugThrowIfNotCheckingIntrinsics());
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
assert(_debugThrowIfNotCheckingIntrinsics());
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
assert(_debugThrowIfNotCheckingIntrinsics());
|
||||
return 0.0;
|
||||
}
|
||||
|
@ -368,25 +368,25 @@ class _RenderLazyBlock extends RenderVirtualViewport<_LazyBlockParentData> {
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
assert(_debugThrowIfNotCheckingIntrinsics());
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
assert(_debugThrowIfNotCheckingIntrinsics());
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
assert(_debugThrowIfNotCheckingIntrinsics());
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
assert(_debugThrowIfNotCheckingIntrinsics());
|
||||
return 0.0;
|
||||
}
|
||||
|
64
packages/flutter/test/rendering/cached_intrinsics_test.dart
Normal file
64
packages/flutter/test/rendering/cached_intrinsics_test.dart
Normal file
@ -0,0 +1,64 @@
|
||||
// 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';
|
||||
|
||||
class RenderTestBox extends RenderBox {
|
||||
double value = 0.0;
|
||||
double next() { value += 1.0; return value; }
|
||||
@override double computeMinIntrinsicWidth(double height) => next();
|
||||
@override double computeMaxIntrinsicWidth(double height) => next();
|
||||
@override double computeMinIntrinsicHeight(double width) => next();
|
||||
@override double computeMaxIntrinsicHeight(double width) => next();
|
||||
}
|
||||
|
||||
void main() {
|
||||
test('Intrinsics cache', () {
|
||||
RenderBox test = new RenderTestBox();
|
||||
|
||||
expect(test.getMinIntrinsicWidth(0.0), equals(1.0));
|
||||
expect(test.getMinIntrinsicWidth(100.0), equals(2.0));
|
||||
expect(test.getMinIntrinsicWidth(200.0), equals(3.0));
|
||||
expect(test.getMinIntrinsicWidth(0.0), equals(1.0));
|
||||
expect(test.getMinIntrinsicWidth(100.0), equals(2.0));
|
||||
expect(test.getMinIntrinsicWidth(200.0), equals(3.0));
|
||||
|
||||
expect(test.getMaxIntrinsicWidth(0.0), equals(4.0));
|
||||
expect(test.getMaxIntrinsicWidth(100.0), equals(5.0));
|
||||
expect(test.getMaxIntrinsicWidth(200.0), equals(6.0));
|
||||
expect(test.getMaxIntrinsicWidth(0.0), equals(4.0));
|
||||
expect(test.getMaxIntrinsicWidth(100.0), equals(5.0));
|
||||
expect(test.getMaxIntrinsicWidth(200.0), equals(6.0));
|
||||
|
||||
expect(test.getMinIntrinsicHeight(0.0), equals(7.0));
|
||||
expect(test.getMinIntrinsicHeight(100.0), equals(8.0));
|
||||
expect(test.getMinIntrinsicHeight(200.0), equals(9.0));
|
||||
expect(test.getMinIntrinsicHeight(0.0), equals(7.0));
|
||||
expect(test.getMinIntrinsicHeight(100.0), equals(8.0));
|
||||
expect(test.getMinIntrinsicHeight(200.0), equals(9.0));
|
||||
|
||||
expect(test.getMaxIntrinsicHeight(0.0), equals(10.0));
|
||||
expect(test.getMaxIntrinsicHeight(100.0), equals(11.0));
|
||||
expect(test.getMaxIntrinsicHeight(200.0), equals(12.0));
|
||||
expect(test.getMaxIntrinsicHeight(0.0), equals(10.0));
|
||||
expect(test.getMaxIntrinsicHeight(100.0), equals(11.0));
|
||||
expect(test.getMaxIntrinsicHeight(200.0), equals(12.0));
|
||||
|
||||
// now read them all again backwards
|
||||
expect(test.getMaxIntrinsicHeight(200.0), equals(12.0));
|
||||
expect(test.getMaxIntrinsicHeight(100.0), equals(11.0));
|
||||
expect(test.getMaxIntrinsicHeight(0.0), equals(10.0));
|
||||
expect(test.getMinIntrinsicHeight(200.0), equals(9.0));
|
||||
expect(test.getMinIntrinsicHeight(100.0), equals(8.0));
|
||||
expect(test.getMinIntrinsicHeight(0.0), equals(7.0));
|
||||
expect(test.getMaxIntrinsicWidth(200.0), equals(6.0));
|
||||
expect(test.getMaxIntrinsicWidth(100.0), equals(5.0));
|
||||
expect(test.getMaxIntrinsicWidth(0.0), equals(4.0));
|
||||
expect(test.getMinIntrinsicWidth(200.0), equals(3.0));
|
||||
expect(test.getMinIntrinsicWidth(100.0), equals(2.0));
|
||||
expect(test.getMinIntrinsicWidth(0.0), equals(1.0));
|
||||
|
||||
});
|
||||
}
|
82
packages/flutter/test/rendering/dynamic_intrinsics_test.dart
Normal file
82
packages/flutter/test/rendering/dynamic_intrinsics_test.dart
Normal file
@ -0,0 +1,82 @@
|
||||
// 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';
|
||||
|
||||
import 'rendering_tester.dart';
|
||||
|
||||
class RenderFixedSize extends RenderBox {
|
||||
double dimension = 100.0;
|
||||
|
||||
void grow() {
|
||||
dimension *= 2.0;
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
@override double computeMinIntrinsicWidth(double height) => dimension;
|
||||
@override double computeMaxIntrinsicWidth(double height) => dimension;
|
||||
@override double computeMinIntrinsicHeight(double width) => dimension;
|
||||
@override double computeMaxIntrinsicHeight(double width) => dimension;
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
size = new Size.square(dimension);
|
||||
}
|
||||
}
|
||||
|
||||
class RenderParentSize extends RenderProxyBox {
|
||||
RenderParentSize({ RenderBox child }) : super(child);
|
||||
|
||||
@override
|
||||
bool get sizedByParent => true;
|
||||
|
||||
@override
|
||||
void performResize() {
|
||||
size = constraints.biggest;
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
child.layout(constraints);
|
||||
}
|
||||
}
|
||||
|
||||
class RenderIntrinsicSize extends RenderProxyBox {
|
||||
RenderIntrinsicSize({ RenderBox child }) : super(child);
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
child.layout(constraints);
|
||||
size = new Size(
|
||||
child.getMinIntrinsicWidth(double.INFINITY),
|
||||
child.getMinIntrinsicHeight(double.INFINITY)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
test('Whether using intrinsics means you get hooked into layout', () {
|
||||
RenderBox root;
|
||||
RenderFixedSize inner;
|
||||
layout(
|
||||
root = new RenderIntrinsicSize(
|
||||
child: new RenderParentSize(
|
||||
child: inner = new RenderFixedSize()
|
||||
)
|
||||
),
|
||||
constraints: new BoxConstraints(
|
||||
minWidth: 0.0,
|
||||
minHeight: 0.0,
|
||||
maxWidth: 1000.0,
|
||||
maxHeight: 1000.0
|
||||
)
|
||||
);
|
||||
expect(root.size, equals(inner.size));
|
||||
|
||||
inner.grow();
|
||||
pumpFrame();
|
||||
expect(root.size, equals(inner.size));
|
||||
});
|
||||
}
|
@ -14,22 +14,22 @@ class RenderTestBox extends RenderBox {
|
||||
final BoxConstraints _intrinsicDimensions;
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
return _intrinsicDimensions.minWidth;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
return _intrinsicDimensions.maxWidth;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return _intrinsicDimensions.minHeight;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return _intrinsicDimensions.maxHeight;
|
||||
}
|
||||
|
||||
|
@ -92,22 +92,22 @@ class RenderSizedBox extends RenderBox {
|
||||
final Size _size;
|
||||
|
||||
@override
|
||||
double getMinIntrinsicWidth(double height) {
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
return _size.width;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicWidth(double height) {
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
return _size.width;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMinIntrinsicHeight(double width) {
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
return _size.height;
|
||||
}
|
||||
|
||||
@override
|
||||
double getMaxIntrinsicHeight(double width) {
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
return _size.height;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user