Chromium Code Reviews| Index: sky/sdk/lib/framework/layout2.dart |
| diff --git a/sky/sdk/lib/framework/layout2.dart b/sky/sdk/lib/framework/layout2.dart |
| index 44b073eae469dbc561e5fd21d5ce17b1073ceb00..c3ae7d70c05360f0dc2d9861de50665e881b549d 100644 |
| --- a/sky/sdk/lib/framework/layout2.dart |
| +++ b/sky/sdk/lib/framework/layout2.dart |
| @@ -23,6 +23,10 @@ class ParentData { |
| const kLayoutDirections = 4; |
| double clamp({double min: 0.0, double value: 0.0, double max: double.INFINITY}) { |
| + assert(min != null); |
| + assert(value != null); |
| + assert(max != null); |
| + |
| if (value > max) |
| value = max; |
| if (value < min) |
| @@ -225,11 +229,6 @@ abstract class RenderNode extends AbstractNode { |
| static bool _debugDoingPaint = false; |
| void markNeedsPaint() { |
| assert(!_debugDoingPaint); |
| - var ancestor = this; |
| - while (ancestor.parent != null) |
| - ancestor = ancestor.parent; |
| - assert(ancestor is RenderView); |
| - ancestor.paintFrame(); |
|
Hixie
2015/05/21 19:45:03
This is the code I was talking about earlier.
|
| } |
| void paint(RenderNodeDisplayList canvas) { } |
| @@ -391,8 +390,28 @@ abstract class ContainerRenderNodeMixin<ChildType extends RenderNode, ParentData |
| // GENERIC BOX RENDERING |
| // Anything that has a concept of x, y, width, height is going to derive from this |
| +class BoxConstraints { |
| + const BoxConstraints({ |
| + this.minWidth: 0.0, |
| + this.maxWidth: double.INFINITY, |
| + this.minHeight: 0.0, |
| + this.maxHeight: double.INFINITY}); |
| + |
| + final double minWidth; |
| + final double maxWidth; |
| + final double minHeight; |
| + final double maxHeight; |
| +} |
| + |
| class BoxDimensions { |
| const BoxDimensions({this.width, this.height}); |
| + |
| + BoxDimensions.withConstraints( |
| + BoxConstraints constraints, {double width: 0.0, double height: 0.0}) { |
| + this.width = clamp(min: minWidth, max: maxWidth, value: width); |
| + this.height = clamp(min: minHeight, max: maxHeight, value: height); |
| + } |
| + |
| final double width; |
| final double height; |
| } |
| @@ -414,39 +433,57 @@ abstract class RenderBox extends RenderNode { |
| // if it must, but it should be as cheap as possible; just get the |
| // dimensions and nothing else (e.g. don't calculate hypothetical |
| // child positions if they're not needed to determine dimensions) |
| - BoxDimensions getIntrinsicDimensions({ |
| - double minWidth: 0.0, |
| - double maxWidth: double.INFINITY, |
| - double minHeight: 0.0, |
| - double maxHeight: double.INFINITY |
| - }) { |
| - return new BoxDimensions( |
| - width: clamp(min: minWidth, max: maxWidth), |
| - height: clamp(min: minHeight, max: maxHeight) |
| - ); |
| + BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { |
| + return new BoxDimensions.withConstraints(constraints); |
| } |
| - void layout({ |
| - double minWidth: 0.0, |
| - double maxWidth: double.INFINITY, |
| - double minHeight: 0.0, |
| - double maxHeight: double.INFINITY, |
| - RenderNode relayoutSubtreeRoot |
| - }) { |
| - width = clamp(min: minWidth, max: maxWidth); |
| - height = clamp(min: minHeight, max: maxHeight); |
| + void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { |
| + setWidth(constraints, 0.0); |
|
Hixie
2015/05/21 19:45:03
how about:
width = constraints.constrainWidth(
|
| + setHeight(constraints, 0.0); |
| layoutDone(); |
| } |
| double width; |
| double height; |
|
Hixie
2015/05/21 19:45:03
I wish we could make these protected and only publ
|
| - void rotate({ |
| - int oldAngle, // 0..3 |
| - int newAngle, // 0..3 |
| - Duration time |
| - }) { } |
| + void setWidth(BoxConstraints constraints, double newWidth) { |
| + width = clamp(min: constraints.minWidth, |
| + max: constraints.maxWidth, |
| + value: newWidth); |
| + } |
| + |
| + void setHeight(BoxConstraints constraints, double newHeight) { |
| + height = clamp(min: constraints.minHeight, |
| + max: constraints.maxHeight, |
| + value: newHeight); |
| + } |
| +} |
| +class BoxDecoration { |
| + BoxDecoration({ |
|
Hixie
2015/05/21 19:45:04
make this a const constructor.
|
| + this.backgroundColor |
| + }); |
| + |
| + final int backgroundColor; |
| +} |
| + |
| +class RenderDecoratedBox extends RenderBox { |
| + BoxDecoration decoration; |
| + |
| + RenderDecoratedBox(this.decoration); |
| + |
| + void paint(RenderNodeDisplayList canvas) { |
| + assert(width != null); |
| + assert(height != null); |
| + |
| + if (decoration == null) |
| + return; |
| + |
| + if (decoration.backgroundColor != null) { |
| + sky.Paint paint = new sky.Paint()..color = decoration.backgroundColor; |
| + canvas.drawRect(new sky.Rect()..setLTRB(0.0, 0.0, width, height), paint); |
| + } |
| + } |
| } |
| @@ -500,12 +537,8 @@ class RenderView extends RenderNode { |
| void relayout() { |
| assert(root != null); |
| - root.layout( |
| - minWidth: width, |
| - maxWidth: width, |
| - minHeight: height, |
| - maxHeight: height |
| - ); |
| + root.layout(new BoxConstraints( |
| + minWidth: width, maxWidth: width, minHeight: height, maxHeight: height)); |
| assert(root.width == width); |
| assert(root.height == height); |
| } |
| @@ -547,16 +580,15 @@ class EdgeDims { |
| class BlockParentData extends BoxParentData with ContainerParentDataMixin<RenderBox> { } |
| -class RenderBlock extends RenderBox with ContainerRenderNodeMixin<RenderBox, BlockParentData> { |
| +class RenderBlock extends RenderDecoratedBox with ContainerRenderNodeMixin<RenderBox, BlockParentData> { |
| // lays out RenderBox children in a vertical stack |
| // uses the maximum width provided by the parent |
| // sizes itself to the height of its child stack |
| RenderBlock({ |
| + BoxDecoration decoration, |
| EdgeDims padding: const EdgeDims(0.0, 0.0, 0.0, 0.0) |
| - }) { |
| - _padding = padding; |
| - } |
| + }) : super(decoration), _padding = padding; |
| EdgeDims _padding; |
| EdgeDims get padding => _padding; |
| @@ -578,42 +610,39 @@ class RenderBlock extends RenderBox with ContainerRenderNodeMixin<RenderBox, Blo |
| // if it must, but it should be as cheap as possible; just get the |
| // dimensions and nothing else (e.g. don't calculate hypothetical |
| // child positions if they're not needed to determine dimensions) |
| - BoxDimensions getIntrinsicDimensions({ |
| - double minWidth: 0.0, |
| - double maxWidth: double.INFINITY, |
| - double minHeight: 0.0, |
| - double maxHeight: double.INFINITY |
| - }) { |
| + BoxDimensions getIntrinsicDimensions(BoxConstraints constraints) { |
| double outerHeight = _padding.top + _padding.bottom; |
| - double outerWidth = clamp(min: minWidth, max: maxWidth); |
| + // TODO(abarth): Shouldn't this have a value: maxWidth? |
|
Hixie
2015/05/21 19:45:04
good question.
if it does, we should assert that
|
| + double outerWidth = clamp(min: constraints.minWidth, |
| + max: constraints.maxWidth); |
| double innerWidth = outerWidth - (_padding.left + _padding.right); |
| RenderBox child = _firstChild; |
| + BoxConstraints constraints = new BoxConstraints(minWidth: innerWidth, |
| + maxWidth: innerWidth); |
| while (child != null) { |
| - outerHeight += child.getIntrinsicDimensions(minWidth: innerWidth, maxWidth: innerWidth).height; |
| + outerHeight += child.getIntrinsicDimensions(constraints).height; |
| assert(child.parentData is BlockParentData); |
| child = child.parentData.nextSibling; |
| } |
| + |
|
Hixie
2015/05/21 19:45:04
Why the blank line?
|
| return new BoxDimensions( |
| width: outerWidth, |
| - height: clamp(min: minHeight, max: maxHeight, value: outerHeight) |
| + height: clamp(min: constraints.minHeight, |
| + max: constraints.maxHeight, |
| + value: outerHeight) |
| ); |
| } |
| double _minHeight; // value cached from parent for relayout call |
| double _maxHeight; // value cached from parent for relayout call |
| - void layout({ |
| - double minWidth: 0.0, |
| - double maxWidth: double.INFINITY, |
| - double minHeight: 0.0, |
| - double maxHeight: double.INFINITY, |
| - RenderNode relayoutSubtreeRoot |
| - }) { |
| + void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { |
| if (relayoutSubtreeRoot != null) |
| saveRelayoutSubtreeRoot(relayoutSubtreeRoot); |
| relayoutSubtreeRoot = relayoutSubtreeRoot == null ? this : relayoutSubtreeRoot; |
| - width = clamp(min: minWidth, max: maxWidth); |
| - _minHeight = minHeight; |
| - _maxHeight = maxHeight; |
| + // TODO(abarth): Shouldn't this be setWidth(constaints, constraints.maxWidth)? |
| + width = clamp(min: constraints.minWidth, max: constraints.maxWidth); |
|
Hixie
2015/05/21 19:45:03
should be consistent with the intrinsic dimensions
|
| + _minHeight = constraints.minHeight; |
| + _maxHeight = constraints.maxHeight; |
| internalLayout(relayoutSubtreeRoot); |
| } |
| @@ -628,9 +657,10 @@ class RenderBlock extends RenderBox with ContainerRenderNodeMixin<RenderBox, Blo |
| double innerWidth = width - (_padding.left + _padding.right); |
| RenderBox child = _firstChild; |
| while (child != null) { |
| - child.layout(minWidth: innerWidth, maxWidth: innerWidth, relayoutSubtreeRoot: relayoutSubtreeRoot); |
| + child.layout(new BoxConstraints(minWidth: innerWidth, maxWidth: innerWidth), |
| + relayoutSubtreeRoot: relayoutSubtreeRoot); |
| assert(child.parentData is BlockParentData); |
| - child.parentData.x = 0.0; |
| + child.parentData.x = 0.0; // TODO(abarth): Shouldn't this be _padding.left? |
|
Hixie
2015/05/21 19:45:03
Yes.
|
| child.parentData.y = y; |
| y += child.height; |
| child = child.parentData.nextSibling; |
| @@ -655,6 +685,7 @@ class RenderBlock extends RenderBox with ContainerRenderNodeMixin<RenderBox, Blo |
| } |
| void paint(RenderNodeDisplayList canvas) { |
| + super.paint(canvas); |
| RenderBox child = _firstChild; |
| while (child != null) { |
| assert(child.parentData is BlockParentData); |
| @@ -694,15 +725,9 @@ class ScaffoldBox extends RenderBox { |
| final RenderBox statusbar; |
| final RenderBox drawer; |
| - void layout({ |
| - double minWidth: 0.0, |
| - double maxWidth: double.INFINITY, |
| - double minHeight: 0.0, |
| - double maxHeight: double.INFINITY, |
| - RenderNode relayoutSubtreeRoot |
| - }) { |
| - width = clamp(min: minWidth, max: maxWidth); |
| - height = clamp(min: minHeight, max: maxHeight); |
| + void layout(BoxConstraints constraints, { RenderNode relayoutSubtreeRoot }) { |
| + setHeight(constraints, 0.0); |
| + setWidth(constraints, 0.0); |
|
Hixie
2015/05/21 19:45:03
change as discussed above.
|
| relayout(); |
| } |
| @@ -712,22 +737,22 @@ class ScaffoldBox extends RenderBox { |
| void relayout() { |
| double bodyHeight = height; |
| if (toolbar != null) { |
| - toolbar.layout(minWidth: width, maxWidth: width, minHeight: kToolbarHeight, maxHeight: kToolbarHeight); |
| + toolbar.layout(new BoxConstraints(minWidth: width, maxWidth: width, minHeight: kToolbarHeight, maxHeight: kToolbarHeight)); |
|
Hixie
2015/05/21 19:45:03
Make a BoxConstraints constructor that takes just
|
| assert(toolbar.parentData is BoxParentData); |
| toolbar.parentData.x = 0.0; |
| toolbar.parentData.y = 0.0; |
| bodyHeight -= kToolbarHeight; |
| } |
| if (statusbar != null) { |
| - statusbar.layout(minWidth: width, maxWidth: width, minHeight: kStatusbarHeight, maxHeight: kStatusbarHeight); |
| + statusbar.layout(new BoxConstraints(minWidth: width, maxWidth: width, minHeight: kStatusbarHeight, maxHeight: kStatusbarHeight)); |
|
Hixie
2015/05/21 19:45:04
ditto
|
| assert(statusbar.parentData is BoxParentData); |
| statusbar.parentData.x = 0.0; |
| statusbar.parentData.y = height - kStatusbarHeight; |
| bodyHeight -= kStatusbarHeight; |
| } |
| - body.layout(minWidth: width, maxWidth: width, minHeight: bodyHeight, maxHeight: bodyHeight); |
| + body.layout(new BoxConstraints(minWidth: width, maxWidth: width, minHeight: bodyHeight, maxHeight: bodyHeight)); |
|
Hixie
2015/05/21 19:45:03
ditto
|
| if (drawer != null) |
| - drawer.layout(minWidth: 0.0, maxWidth: width, minHeight: height, maxHeight: height); |
| + drawer.layout(new BoxConstraints(minWidth: 0.0, maxWidth: width, minHeight: height, maxHeight: height)); |
| layoutDone(); |
| } |