Commit 95277953 authored by Adam Barth's avatar 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.
parent 48f600f8
...@@ -452,7 +452,7 @@ class RenderBoxToRenderSectorAdapter extends RenderBox { ...@@ -452,7 +452,7 @@ class RenderBoxToRenderSectorAdapter extends RenderBox {
Size getIntrinsicDimensions(BoxConstraints constraints) { Size getIntrinsicDimensions(BoxConstraints constraints) {
assert(child is RenderSector); assert(child is RenderSector);
assert(child.parentData is SectorParentData); 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; double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius;
SectorDimensions childDimensions = child.getIntrinsicDimensions(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), innerRadius); SectorDimensions childDimensions = child.getIntrinsicDimensions(new SectorConstraints(maxDeltaRadius: maxChildDeltaRadius), innerRadius);
double dimension = (innerRadius + childDimensions.deltaRadius) * 2.0; double dimension = (innerRadius + childDimensions.deltaRadius) * 2.0;
...@@ -464,7 +464,7 @@ class RenderBoxToRenderSectorAdapter extends RenderBox { ...@@ -464,7 +464,7 @@ class RenderBoxToRenderSectorAdapter extends RenderBox {
size = constraints.constrain(Size.zero); size = constraints.constrain(Size.zero);
} else { } else {
assert(child is RenderSector); 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; double maxChildDeltaRadius = math.min(constraints.maxWidth, constraints.maxHeight) / 2.0 - innerRadius;
assert(child.parentData is SectorParentData); assert(child.parentData is SectorParentData);
child.parentData.radius = innerRadius; child.parentData.radius = innerRadius;
......
...@@ -53,7 +53,7 @@ HAL: This mission is too important for me to allow you to jeopardize it.'''; ...@@ -53,7 +53,7 @@ HAL: This mission is too important for me to allow you to jeopardize it.''';
Component createSeparator() { Component createSeparator() {
return new Container( 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), margin: const EdgeDims.symmetric(vertical: 10.0, horizontal: 64.0),
decoration: const BoxDecoration( decoration: const BoxDecoration(
border: const Border( border: const Border(
......
...@@ -314,7 +314,7 @@ class RenderBlockViewport extends RenderBlockBase { ...@@ -314,7 +314,7 @@ class RenderBlockViewport extends RenderBlockBase {
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(BoxConstraints constraints) {
if (isVertical) if (isVertical)
return _getIntrinsicDimension(constraints, maxCrossAxisDimensionCallback, constraints.constrainWidth); 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) { double getMinIntrinsicHeight(BoxConstraints constraints) {
...@@ -326,7 +326,7 @@ class RenderBlockViewport extends RenderBlockBase { ...@@ -326,7 +326,7 @@ class RenderBlockViewport extends RenderBlockBase {
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(BoxConstraints constraints) {
if (!isVertical) if (!isVertical)
return _getIntrinsicDimension(constraints, maxCrossAxisDimensionCallback, constraints.constrainHeight); 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 // We don't override computeDistanceToActualBaseline(), because we
......
...@@ -23,7 +23,22 @@ class _DebugSize extends Size { ...@@ -23,7 +23,22 @@ class _DebugSize extends Size {
final bool _canBeUsedByParent; 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 { class BoxConstraints extends Constraints {
/// Constructs box constraints with the given constraints
const BoxConstraints({ const BoxConstraints({
this.minWidth: 0.0, this.minWidth: 0.0,
this.maxWidth: double.INFINITY, this.maxWidth: double.INFINITY,
...@@ -31,12 +46,19 @@ class BoxConstraints extends Constraints { ...@@ -31,12 +46,19 @@ class BoxConstraints extends Constraints {
this.maxHeight: double.INFINITY 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) BoxConstraints.tight(Size size)
: minWidth = size.width, : minWidth = size.width,
maxWidth = size.width, maxWidth = size.width,
minHeight = size.height, minHeight = size.height,
maxHeight = size.height; maxHeight = size.height;
/// Constructs box constraints that require the given width or height
const BoxConstraints.tightFor({ const BoxConstraints.tightFor({
double width, double width,
double height double height
...@@ -45,43 +67,41 @@ class BoxConstraints extends Constraints { ...@@ -45,43 +67,41 @@ class BoxConstraints extends Constraints {
minHeight = height != null ? height : 0.0, minHeight = height != null ? height : 0.0,
maxHeight = height != null ? height : double.INFINITY; maxHeight = height != null ? height : double.INFINITY;
/// Constructs box constraints that forbid sizes larger than the given size
BoxConstraints.loose(Size size) BoxConstraints.loose(Size size)
: minWidth = 0.0, : minWidth = 0.0,
maxWidth = size.width, maxWidth = size.width,
minHeight = 0.0, minHeight = 0.0,
maxHeight = size.height; maxHeight = size.height;
const BoxConstraints.expandWidth({ /// Constructs box constraints that expand to fill another box contraints
this.maxHeight: double.INFINITY ///
}): minWidth = double.INFINITY, /// If width or height is given, the constraints will require exactly the
maxWidth = double.INFINITY, /// given value in the given dimension.
minHeight = 0.0; const BoxConstraints.expand({
double width,
const BoxConstraints.expandHeight({ double height
this.maxWidth: double.INFINITY }): minWidth = width != null ? width : double.INFINITY,
}): minWidth = 0.0, maxWidth = width != null ? width : double.INFINITY,
minHeight = double.INFINITY, minHeight = height != null ? height : double.INFINITY,
maxHeight = double.INFINITY; maxHeight = height != null ? height : double.INFINITY;
static const BoxConstraints expand = const BoxConstraints( /// Returns new box constraints that are smaller by the given edge dimensions
minWidth: double.INFINITY,
maxWidth: double.INFINITY,
minHeight: double.INFINITY,
maxHeight: double.INFINITY
);
BoxConstraints deflate(EdgeDims edges) { BoxConstraints deflate(EdgeDims edges) {
assert(edges != null); assert(edges != null);
double horizontal = edges.left + edges.right; double horizontal = edges.left + edges.right;
double vertical = edges.top + edges.bottom; 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( return new BoxConstraints(
minWidth: math.max(0.0, minWidth - horizontal), minWidth: deflatedMinWidth,
maxWidth: maxWidth - horizontal, maxWidth: math.max(deflatedMinWidth, maxWidth - horizontal),
minHeight: math.max(0.0, minHeight - vertical), minHeight: deflatedMinHeight,
maxHeight: maxHeight - vertical maxHeight: math.max(deflatedMinHeight, maxHeight - vertical)
); );
} }
/// Returns new box constraints that remove the minimum width and height requirements
BoxConstraints loosen() { BoxConstraints loosen() {
return new BoxConstraints( return new BoxConstraints(
minWidth: 0.0, minWidth: 0.0,
...@@ -91,7 +111,8 @@ class BoxConstraints extends Constraints { ...@@ -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( return new BoxConstraints(
minWidth: clamp(min: constraints.minWidth, max: constraints.maxWidth, value: minWidth), minWidth: clamp(min: constraints.minWidth, max: constraints.maxWidth, value: minWidth),
maxWidth: clamp(min: constraints.minWidth, max: constraints.maxWidth, value: maxWidth), maxWidth: clamp(min: constraints.minWidth, max: constraints.maxWidth, value: maxWidth),
...@@ -100,81 +121,63 @@ class BoxConstraints extends Constraints { ...@@ -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), return new BoxConstraints(minWidth: math.max(math.min(maxWidth, width), minWidth),
maxWidth: math.max(math.min(maxWidth, width), minWidth), maxWidth: math.max(math.min(maxWidth, width), minWidth),
minHeight: minHeight, minHeight: minHeight,
maxHeight: maxHeight); maxHeight: maxHeight);
} }
BoxConstraints applyMinWidth(double newMinWidth) { /// Returns new box constraints with a tight height as close to the given height as possible while still respecting the original box constraints
return new BoxConstraints(minWidth: math.max(minWidth, newMinWidth), BoxConstraints tightenHeight(double height) {
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) {
return new BoxConstraints(minWidth: minWidth, return new BoxConstraints(minWidth: minWidth,
maxWidth: maxWidth, maxWidth: maxWidth,
minHeight: math.max(math.min(maxHeight, height), minHeight), minHeight: math.max(math.min(maxHeight, height), minHeight),
maxHeight: math.max(math.min(maxHeight, height), minHeight)); maxHeight: math.max(math.min(maxHeight, height), minHeight));
} }
BoxConstraints applyMinHeight(double newMinHeight) { /// Returns box constraints with the same width constraints but with unconstrainted height
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));
}
BoxConstraints widthConstraints() => new BoxConstraints(minWidth: minWidth, maxWidth: maxWidth); 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); BoxConstraints heightConstraints() => new BoxConstraints(minHeight: minHeight, maxHeight: maxHeight);
final double minWidth; /// Returns the width that both satisfies the constraints and is as close as possible to the given width
final double maxWidth;
final double minHeight;
final double maxHeight;
double constrainWidth([double width = double.INFINITY]) { double constrainWidth([double width = double.INFINITY]) {
return clamp(min: minWidth, max: maxWidth, value: width); 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]) { double constrainHeight([double height = double.INFINITY]) {
return clamp(min: minHeight, max: maxHeight, value: height); 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 constrain(Size size) {
Size result = new Size(constrainWidth(size.width), constrainHeight(size.height)); Size result = new Size(constrainWidth(size.width), constrainHeight(size.height));
if (size is _DebugSize) if (size is _DebugSize)
result = new _DebugSize(result, size._owner, size._canBeUsedByParent); result = new _DebugSize(result, size._owner, size._canBeUsedByParent);
return result; return result;
} }
/// The biggest size that satisifes the constraints
Size get biggest => new Size(constrainWidth(), constrainHeight()); 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; bool get hasTightWidth => minWidth >= maxWidth;
/// Whether there is exactly one height value that satisfies the constraints
bool get hasTightHeight => minHeight >= maxHeight; bool get hasTightHeight => minHeight >= maxHeight;
/// Whether there is exactly one size that satifies the constraints
bool get isTight => hasTightWidth && hasTightHeight; 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)) && return (minWidth <= size.width) && (size.width <= math.max(minWidth, maxWidth)) &&
(minHeight <= size.height) && (size.height <= math.max(minHeight, maxHeight)); (minHeight <= size.height) && (size.height <= math.max(minHeight, maxHeight));
} }
...@@ -323,7 +326,7 @@ abstract class RenderBox extends RenderObject { ...@@ -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'; 'See https://github.com/domokit/sky_engine/blob/master/sky/packages/sky/lib/src/widgets/sizing.md#user-content-unbounded-constraints';
return !_size.isInfinite; return !_size.isInfinite;
}); });
bool result = constraints.contains(_size); bool result = constraints.isSatisfiedBy(_size);
if (!result) if (!result)
print("${this.runtimeType} does not meet its constraints. Constraints: $constraints, size: $_size"); print("${this.runtimeType} does not meet its constraints. Constraints: $constraints, size: $_size");
return result; return result;
......
...@@ -85,7 +85,7 @@ class RenderImage extends RenderBox { ...@@ -85,7 +85,7 @@ class RenderImage extends RenderBox {
constraints = new BoxConstraints.tightFor( constraints = new BoxConstraints.tightFor(
width: _width, width: _width,
height: _height height: _height
).apply(constraints); ).enforce(constraints);
if (constraints.isTight || _image == null) if (constraints.isTight || _image == null)
return constraints.smallest; return constraints.smallest;
......
...@@ -92,34 +92,34 @@ class RenderConstrainedBox extends RenderProxyBox { ...@@ -92,34 +92,34 @@ class RenderConstrainedBox extends RenderProxyBox {
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(BoxConstraints constraints) {
if (child != null) if (child != null)
return child.getMinIntrinsicWidth(_additionalConstraints.apply(constraints)); return child.getMinIntrinsicWidth(_additionalConstraints.enforce(constraints));
return _additionalConstraints.apply(constraints).constrainWidth(0.0); return _additionalConstraints.enforce(constraints).constrainWidth(0.0);
} }
double getMaxIntrinsicWidth(BoxConstraints constraints) { double getMaxIntrinsicWidth(BoxConstraints constraints) {
if (child != null) if (child != null)
return child.getMaxIntrinsicWidth(_additionalConstraints.apply(constraints)); return child.getMaxIntrinsicWidth(_additionalConstraints.enforce(constraints));
return _additionalConstraints.apply(constraints).constrainWidth(0.0); return _additionalConstraints.enforce(constraints).constrainWidth(0.0);
} }
double getMinIntrinsicHeight(BoxConstraints constraints) { double getMinIntrinsicHeight(BoxConstraints constraints) {
if (child != null) if (child != null)
return child.getMinIntrinsicHeight(_additionalConstraints.apply(constraints)); return child.getMinIntrinsicHeight(_additionalConstraints.enforce(constraints));
return _additionalConstraints.apply(constraints).constrainHeight(0.0); return _additionalConstraints.enforce(constraints).constrainHeight(0.0);
} }
double getMaxIntrinsicHeight(BoxConstraints constraints) { double getMaxIntrinsicHeight(BoxConstraints constraints) {
if (child != null) if (child != null)
return child.getMaxIntrinsicHeight(_additionalConstraints.apply(constraints)); return child.getMaxIntrinsicHeight(_additionalConstraints.enforce(constraints));
return _additionalConstraints.apply(constraints).constrainHeight(0.0); return _additionalConstraints.enforce(constraints).constrainHeight(0.0);
} }
void performLayout() { void performLayout() {
if (child != null) { if (child != null) {
child.layout(_additionalConstraints.apply(constraints), parentUsesSize: true); child.layout(_additionalConstraints.enforce(constraints), parentUsesSize: true);
size = child.size; size = child.size;
} else { } else {
size = _additionalConstraints.apply(constraints).constrain(Size.zero); size = _additionalConstraints.enforce(constraints).constrain(Size.zero);
} }
} }
...@@ -218,7 +218,7 @@ class RenderShrinkWrapWidth extends RenderProxyBox { ...@@ -218,7 +218,7 @@ class RenderShrinkWrapWidth extends RenderProxyBox {
return constraints; return constraints;
double width = child.getMaxIntrinsicWidth(constraints); double width = child.getMaxIntrinsicWidth(constraints);
assert(width == constraints.constrainWidth(width)); assert(width == constraints.constrainWidth(width));
return constraints.applyWidth(applyStep(width, _stepWidth)); return constraints.tightenWidth(applyStep(width, _stepWidth));
} }
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(BoxConstraints constraints) {
...@@ -250,7 +250,7 @@ class RenderShrinkWrapWidth extends RenderProxyBox { ...@@ -250,7 +250,7 @@ class RenderShrinkWrapWidth extends RenderProxyBox {
if (child != null) { if (child != null) {
BoxConstraints childConstraints = _getInnerConstraints(constraints); BoxConstraints childConstraints = _getInnerConstraints(constraints);
if (_stepHeight != null) if (_stepHeight != null)
childConstraints.applyHeight(getMaxIntrinsicHeight(childConstraints)); childConstraints.tightenHeight(getMaxIntrinsicHeight(childConstraints));
child.layout(childConstraints, parentUsesSize: true); child.layout(childConstraints, parentUsesSize: true);
size = child.size; size = child.size;
} else { } else {
...@@ -281,7 +281,7 @@ class RenderShrinkWrapHeight extends RenderProxyBox { ...@@ -281,7 +281,7 @@ class RenderShrinkWrapHeight extends RenderProxyBox {
return constraints; return constraints;
double height = child.getMaxIntrinsicHeight(constraints); double height = child.getMaxIntrinsicHeight(constraints);
assert(height == constraints.constrainHeight(height)); assert(height == constraints.constrainHeight(height));
return constraints.applyHeight(height); return constraints.tightenHeight(height);
} }
double getMinIntrinsicWidth(BoxConstraints constraints) { double getMinIntrinsicWidth(BoxConstraints constraints) {
......
...@@ -155,10 +155,10 @@ class RenderStack extends RenderBox with ContainerRenderObjectMixin<RenderBox, S ...@@ -155,10 +155,10 @@ class RenderStack extends RenderBox with ContainerRenderObjectMixin<RenderBox, S
BoxConstraints childConstraints = const BoxConstraints(); BoxConstraints childConstraints = const BoxConstraints();
if (childData.left != null && childData.right != null) 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) 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); child.layout(childConstraints, parentUsesSize: true);
......
...@@ -246,9 +246,9 @@ class SizedBox extends OneChildRenderObjectWrapper { ...@@ -246,9 +246,9 @@ class SizedBox extends OneChildRenderObjectWrapper {
BoxConstraints _additionalConstraints() { BoxConstraints _additionalConstraints() {
BoxConstraints result = const BoxConstraints(); BoxConstraints result = const BoxConstraints();
if (width != null) if (width != null)
result = result.applyWidth(width); result = result.tightenWidth(width);
if (height != null) if (height != null)
result = result.applyHeight(height); result = result.tightenHeight(height);
return result; return result;
} }
...@@ -430,7 +430,7 @@ class Container extends Component { ...@@ -430,7 +430,7 @@ class Container extends Component {
Widget current = child; Widget current = child;
if (child == null && (width == null || height == null)) if (child == null && (width == null || height == null))
current = new ConstrainedBox(constraints: BoxConstraints.expand); current = new ConstrainedBox(constraints: const BoxConstraints.expand());
EdgeDims effectivePadding = _paddingIncludingBorder; EdgeDims effectivePadding = _paddingIncludingBorder;
if (effectivePadding != null) if (effectivePadding != null)
......
...@@ -22,7 +22,7 @@ void main() { ...@@ -22,7 +22,7 @@ void main() {
test('Flex and padding', () { test('Flex and padding', () {
RenderBox size = new RenderConstrainedBox( RenderBox size = new RenderConstrainedBox(
additionalConstraints: new BoxConstraints().applyHeight(100.0) additionalConstraints: new BoxConstraints().tightenHeight(100.0)
); );
RenderBox inner = new RenderDecoratedBox( RenderBox inner = new RenderDecoratedBox(
decoration: new BoxDecoration( decoration: new BoxDecoration(
......
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