提交 79c280a7 编写于 作者: A Adam Barth

Document and bring sanity to BoxConstraints

Turns out many of the functions on BoxConstraints weren't used or had callers
that could easily be updated to other functions. I've added dartdoc to all the
public functions as well as renamed some functions that had similar names but
did different things.
上级 ee24e505
......@@ -452,7 +452,7 @@ class RenderBoxToRenderSectorAdapter extends RenderBox {
Size getIntrinsicDimensions(BoxConstraints constraints) {
assert(child is RenderSector);
assert(child.parentData is SectorParentData);
assert(!constraints.isInfinite);
assert(constraints.maxWidth < double.INFINITY || constraints.maxHeight < double.INFINITY);
double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius;
SectorDimensions childDimensions = child.getIntrinsicDimensions(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), innerRadius);
double dimension = (innerRadius + childDimensions.deltaRadius) * 2.0;
......@@ -464,7 +464,7 @@ class RenderBoxToRenderSectorAdapter extends RenderBox {
size = constraints.constrain(Size.zero);
} else {
assert(child is RenderSector);
assert(!constraints.isInfinite);
assert(constraints.maxWidth < double.INFINITY || constraints.maxHeight < double.INFINITY);
double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius;
assert(child.parentData is SectorParentData);
child.parentData.radius = innerRadius;
......
......@@ -53,7 +53,7 @@ HAL: This mission is too important for me to allow you to jeopardize it.''';
Component createSeparator() {
return new Container(
constraints: const BoxConstraints.expandWidth(maxHeight: 0.0),
constraints: const BoxConstraints.expand(height: 0.0),
margin: const EdgeDims.symmetric(vertical: 10.0, horizontal: 64.0),
decoration: const BoxDecoration(
border: const Border(
......
......@@ -314,7 +314,7 @@ class RenderBlockViewport extends RenderBlockBase {
double getMaxIntrinsicWidth(BoxConstraints constraints) {
if (isVertical)
return _getIntrinsicDimension(constraints, maxCrossAxisDimensionCallback, constraints.constrainWidth);
return _getIntrinsicDimension(constraints, totalExtentCallback, new BoxConstraints(minWidth: minExtent).apply(constraints).constrainWidth);
return _getIntrinsicDimension(constraints, totalExtentCallback, new BoxConstraints(minWidth: minExtent).enforce(constraints).constrainWidth);
}
double getMinIntrinsicHeight(BoxConstraints constraints) {
......@@ -326,7 +326,7 @@ class RenderBlockViewport extends RenderBlockBase {
double getMaxIntrinsicHeight(BoxConstraints constraints) {
if (!isVertical)
return _getIntrinsicDimension(constraints, maxCrossAxisDimensionCallback, constraints.constrainHeight);
return _getIntrinsicDimension(constraints, totalExtentCallback, new BoxConstraints(minHeight: minExtent).apply(constraints).constrainHeight);
return _getIntrinsicDimension(constraints, totalExtentCallback, new BoxConstraints(minHeight: minExtent).enforce(constraints).constrainHeight);
}
// We don't override computeDistanceToActualBaseline(), because we
......
......@@ -23,7 +23,22 @@ class _DebugSize extends Size {
final bool _canBeUsedByParent;
}
/// Immutable layout constraints for box layout
///
/// A size respects a BoxConstraints if, and only if, all of the following
/// relations hold:
///
/// * `minWidth <= size.width <= constraints.maxWidth`
/// * `minHeight <= size.height <= maxHeight`
///
/// The constraints themselves must satisfy these relations:
///
/// * `0.0 <= minWidth <= maxWidth <= double.INFINITY`
/// * `0.0 <= minHeight <= maxHeight <= double.INFINITY`
///
/// Note: `double.INFINITY` is a legal value for each constraint.
class BoxConstraints extends Constraints {
/// Constructs box constraints with the given constraints
const BoxConstraints({
this.minWidth: 0.0,
this.maxWidth: double.INFINITY,
......@@ -31,12 +46,19 @@ class BoxConstraints extends Constraints {
this.maxHeight: double.INFINITY
});
final double minWidth;
final double maxWidth;
final double minHeight;
final double maxHeight;
/// Constructs box constraints that is respected only by the given size
BoxConstraints.tight(Size size)
: minWidth = size.width,
maxWidth = size.width,
minHeight = size.height,
maxHeight = size.height;
/// Constructs box constraints that require the given width or height
const BoxConstraints.tightFor({
double width,
double height
......@@ -45,43 +67,41 @@ class BoxConstraints extends Constraints {
minHeight = height != null ? height : 0.0,
maxHeight = height != null ? height : double.INFINITY;
/// Constructs box constraints that forbid sizes larger than the given size
BoxConstraints.loose(Size size)
: minWidth = 0.0,
maxWidth = size.width,
minHeight = 0.0,
maxHeight = size.height;
const BoxConstraints.expandWidth({
this.maxHeight: double.INFINITY
}): minWidth = double.INFINITY,
maxWidth = double.INFINITY,
minHeight = 0.0;
const BoxConstraints.expandHeight({
this.maxWidth: double.INFINITY
}): minWidth = 0.0,
minHeight = double.INFINITY,
maxHeight = double.INFINITY;
static const BoxConstraints expand = const BoxConstraints(
minWidth: double.INFINITY,
maxWidth: double.INFINITY,
minHeight: double.INFINITY,
maxHeight: double.INFINITY
);
/// Constructs box constraints that expand to fill another box contraints
///
/// If width or height is given, the constraints will require exactly the
/// given value in the given dimension.
const BoxConstraints.expand({
double width,
double height
}): minWidth = width != null ? width : double.INFINITY,
maxWidth = width != null ? width : double.INFINITY,
minHeight = height != null ? height : double.INFINITY,
maxHeight = height != null ? height : double.INFINITY;
/// Returns new box constraints that are smaller by the given edge dimensions
BoxConstraints deflate(EdgeDims edges) {
assert(edges != null);
double horizontal = edges.left + edges.right;
double vertical = edges.top + edges.bottom;
double deflatedMinWidth = math.max(0.0, minWidth - horizontal);
double deflatedMinHeight = math.max(0.0, minHeight - vertical);
return new BoxConstraints(
minWidth: math.max(0.0, minWidth - horizontal),
maxWidth: maxWidth - horizontal,
minHeight: math.max(0.0, minHeight - vertical),
maxHeight: maxHeight - vertical
minWidth: deflatedMinWidth,
maxWidth: math.max(deflatedMinWidth, maxWidth - horizontal),
minHeight: deflatedMinHeight,
maxHeight: math.max(deflatedMinHeight, maxHeight - vertical)
);
}
/// Returns new box constraints that remove the minimum width and height requirements
BoxConstraints loosen() {
return new BoxConstraints(
minWidth: 0.0,
......@@ -91,7 +111,8 @@ class BoxConstraints extends Constraints {
);
}
BoxConstraints apply(BoxConstraints constraints) {
/// Returns new box constraints that respect the given constraints while being as close as possible to the original constraints
BoxConstraints enforce(BoxConstraints constraints) {
return new BoxConstraints(
minWidth: clamp(min: constraints.minWidth, max: constraints.maxWidth, value: minWidth),
maxWidth: clamp(min: constraints.minWidth, max: constraints.maxWidth, value: maxWidth),
......@@ -100,81 +121,63 @@ class BoxConstraints extends Constraints {
);
}
BoxConstraints applyWidth(double width) {
/// Returns new box constraints with a tight width as close to the given width as possible while still respecting the original box constraints
BoxConstraints tightenWidth(double width) {
return new BoxConstraints(minWidth: math.max(math.min(maxWidth, width), minWidth),
maxWidth: math.max(math.min(maxWidth, width), minWidth),
minHeight: minHeight,
maxHeight: maxHeight);
}
BoxConstraints applyMinWidth(double newMinWidth) {
return new BoxConstraints(minWidth: math.max(minWidth, newMinWidth),
maxWidth: math.max(maxWidth, newMinWidth),
minHeight: minHeight,
maxHeight: maxHeight);
}
BoxConstraints applyMaxWidth(double newMaxWidth) {
return new BoxConstraints(minWidth: minWidth,
maxWidth: math.min(maxWidth, newMaxWidth),
minHeight: minHeight,
maxHeight: maxHeight);
}
BoxConstraints applyHeight(double height) {
/// Returns new box constraints with a tight height as close to the given height as possible while still respecting the original box constraints
BoxConstraints tightenHeight(double height) {
return new BoxConstraints(minWidth: minWidth,
maxWidth: maxWidth,
minHeight: math.max(math.min(maxHeight, height), minHeight),
maxHeight: math.max(math.min(maxHeight, height), minHeight));
}
BoxConstraints applyMinHeight(double newMinHeight) {
return new BoxConstraints(minWidth: minWidth,
maxWidth: maxWidth,
minHeight: math.max(minHeight, newMinHeight),
maxHeight: math.max(maxHeight, newMinHeight));
}
BoxConstraints applyMaxHeight(double newMaxHeight) {
return new BoxConstraints(minWidth: minWidth,
maxWidth: maxWidth,
minHeight: minHeight,
maxHeight: math.min(maxHeight, newMaxHeight));
}
/// Returns box constraints with the same width constraints but with unconstrainted height
BoxConstraints widthConstraints() => new BoxConstraints(minWidth: minWidth, maxWidth: maxWidth);
/// Returns box constraints with the same height constraints but with unconstrainted width
BoxConstraints heightConstraints() => new BoxConstraints(minHeight: minHeight, maxHeight: maxHeight);
final double minWidth;
final double maxWidth;
final double minHeight;
final double maxHeight;
/// Returns the width that both satisfies the constraints and is as close as possible to the given width
double constrainWidth([double width = double.INFINITY]) {
return clamp(min: minWidth, max: maxWidth, value: width);
}
/// Returns the height that both satisfies the constraints and is as close as possible to the given height
double constrainHeight([double height = double.INFINITY]) {
return clamp(min: minHeight, max: maxHeight, value: height);
}
/// Returns the size that both satisfies the constraints and is as close as possible to the given size
Size constrain(Size size) {
Size result = new Size(constrainWidth(size.width), constrainHeight(size.height));
if (size is _DebugSize)
result = new _DebugSize(result, size._owner, size._canBeUsedByParent);
return result;
}
/// The biggest size that satisifes the constraints
Size get biggest => new Size(constrainWidth(), constrainHeight());
Size get smallest => new Size(constrainWidth(0.0), constrainHeight(0.0));
bool get isInfinite => maxWidth >= double.INFINITY && maxHeight >= double.INFINITY;
/// The smallest size that satisfies the constraints
Size get smallest => new Size(constrainWidth(0.0), constrainHeight(0.0));
/// Whether there is exactly one width value that satisfies the constraints
bool get hasTightWidth => minWidth >= maxWidth;
/// Whether there is exactly one height value that satisfies the constraints
bool get hasTightHeight => minHeight >= maxHeight;
/// Whether there is exactly one size that satifies the constraints
bool get isTight => hasTightWidth && hasTightHeight;
bool contains(Size size) {
/// Whether the given size satisfies the constraints
bool isSatisfiedBy(Size size) {
return (minWidth <= size.width) && (size.width <= math.max(minWidth, maxWidth)) &&
(minHeight <= size.height) && (size.height <= math.max(minHeight, maxHeight));
}
......@@ -323,7 +326,7 @@ abstract class RenderBox extends RenderObject {
'See https://github.com/domokit/sky_engine/blob/master/sky/packages/sky/lib/src/widgets/sizing.md#user-content-unbounded-constraints';
return !_size.isInfinite;
});
bool result = constraints.contains(_size);
bool result = constraints.isSatisfiedBy(_size);
if (!result)
print("${this.runtimeType} does not meet its constraints. Constraints: $constraints, size: $_size");
return result;
......
......@@ -85,7 +85,7 @@ class RenderImage extends RenderBox {
constraints = new BoxConstraints.tightFor(
width: _width,
height: _height
).apply(constraints);
).enforce(constraints);
if (constraints.isTight || _image == null)
return constraints.smallest;
......
......@@ -92,34 +92,34 @@ class RenderConstrainedBox extends RenderProxyBox {
double getMinIntrinsicWidth(BoxConstraints constraints) {
if (child != null)
return child.getMinIntrinsicWidth(_additionalConstraints.apply(constraints));
return _additionalConstraints.apply(constraints).constrainWidth(0.0);
return child.getMinIntrinsicWidth(_additionalConstraints.enforce(constraints));
return _additionalConstraints.enforce(constraints).constrainWidth(0.0);
}
double getMaxIntrinsicWidth(BoxConstraints constraints) {
if (child != null)
return child.getMaxIntrinsicWidth(_additionalConstraints.apply(constraints));
return _additionalConstraints.apply(constraints).constrainWidth(0.0);
return child.getMaxIntrinsicWidth(_additionalConstraints.enforce(constraints));
return _additionalConstraints.enforce(constraints).constrainWidth(0.0);
}
double getMinIntrinsicHeight(BoxConstraints constraints) {
if (child != null)
return child.getMinIntrinsicHeight(_additionalConstraints.apply(constraints));
return _additionalConstraints.apply(constraints).constrainHeight(0.0);
return child.getMinIntrinsicHeight(_additionalConstraints.enforce(constraints));
return _additionalConstraints.enforce(constraints).constrainHeight(0.0);
}
double getMaxIntrinsicHeight(BoxConstraints constraints) {
if (child != null)
return child.getMaxIntrinsicHeight(_additionalConstraints.apply(constraints));
return _additionalConstraints.apply(constraints).constrainHeight(0.0);
return child.getMaxIntrinsicHeight(_additionalConstraints.enforce(constraints));
return _additionalConstraints.enforce(constraints).constrainHeight(0.0);
}
void performLayout() {
if (child != null) {
child.layout(_additionalConstraints.apply(constraints), parentUsesSize: true);
child.layout(_additionalConstraints.enforce(constraints), parentUsesSize: true);
size = child.size;
} else {
size = _additionalConstraints.apply(constraints).constrain(Size.zero);
size = _additionalConstraints.enforce(constraints).constrain(Size.zero);
}
}
......@@ -218,7 +218,7 @@ class RenderShrinkWrapWidth extends RenderProxyBox {
return constraints;
double width = child.getMaxIntrinsicWidth(constraints);
assert(width == constraints.constrainWidth(width));
return constraints.applyWidth(applyStep(width, _stepWidth));
return constraints.tightenWidth(applyStep(width, _stepWidth));
}
double getMinIntrinsicWidth(BoxConstraints constraints) {
......@@ -250,7 +250,7 @@ class RenderShrinkWrapWidth extends RenderProxyBox {
if (child != null) {
BoxConstraints childConstraints = _getInnerConstraints(constraints);
if (_stepHeight != null)
childConstraints.applyHeight(getMaxIntrinsicHeight(childConstraints));
childConstraints.tightenHeight(getMaxIntrinsicHeight(childConstraints));
child.layout(childConstraints, parentUsesSize: true);
size = child.size;
} else {
......@@ -281,7 +281,7 @@ class RenderShrinkWrapHeight extends RenderProxyBox {
return constraints;
double height = child.getMaxIntrinsicHeight(constraints);
assert(height == constraints.constrainHeight(height));
return constraints.applyHeight(height);
return constraints.tightenHeight(height);
}
double getMinIntrinsicWidth(BoxConstraints constraints) {
......
......@@ -155,10 +155,10 @@ class RenderStack extends RenderBox with ContainerRenderObjectMixin<RenderBox, S
BoxConstraints childConstraints = const BoxConstraints();
if (childData.left != null && childData.right != null)
childConstraints = childConstraints.applyWidth(size.width - childData.right - childData.left);
childConstraints = childConstraints.tightenWidth(size.width - childData.right - childData.left);
if (childData.top != null && childData.bottom != null)
childConstraints = childConstraints.applyHeight(size.height - childData.bottom - childData.top);
childConstraints = childConstraints.tightenHeight(size.height - childData.bottom - childData.top);
child.layout(childConstraints, parentUsesSize: true);
......
......@@ -246,9 +246,9 @@ class SizedBox extends OneChildRenderObjectWrapper {
BoxConstraints _additionalConstraints() {
BoxConstraints result = const BoxConstraints();
if (width != null)
result = result.applyWidth(width);
result = result.tightenWidth(width);
if (height != null)
result = result.applyHeight(height);
result = result.tightenHeight(height);
return result;
}
......@@ -430,7 +430,7 @@ class Container extends Component {
Widget current = child;
if (child == null && (width == null || height == null))
current = new ConstrainedBox(constraints: BoxConstraints.expand);
current = new ConstrainedBox(constraints: const BoxConstraints.expand());
EdgeDims effectivePadding = _paddingIncludingBorder;
if (effectivePadding != null)
......
......@@ -22,7 +22,7 @@ void main() {
test('Flex and padding', () {
RenderBox size = new RenderConstrainedBox(
additionalConstraints: new BoxConstraints().applyHeight(100.0)
additionalConstraints: new BoxConstraints().tightenHeight(100.0)
);
RenderBox inner = new RenderDecoratedBox(
decoration: new BoxDecoration(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册