Verify that callers correctly set parentUsesSize if they use the child's size (and fix a few cases that didn't).

This introduces a bunch of code that should only run in debug builds, but we don't have #ifdefs yet.

R=abarth@chromium.org

Review URL: https://codereview.chromium.org/1182933003.
This commit is contained in:
Hixie 2015-06-12 17:09:57 -07:00
parent d59f88b826
commit 9fc0a3f2ae
7 changed files with 71 additions and 16 deletions

View File

@ -8,6 +8,7 @@ part of dart.sky;
/// Think of this as a vector from Point(0,0) to Point(size.width, size.height)
class Size {
const Size(this.width, this.height);
Size.copy(Size source) : width = source.width, height = source.height;
const Size.fromWidth(this.width) : height = double.INFINITY;
const Size.fromHeight(this.height) : width = double.INFINITY;

View File

@ -71,12 +71,8 @@ void rotate(double timeStamp) {
transformBox.translate(transformBox.size.width / 2.0, transformBox.size.height / 2.0);
transformBox.rotateZ(delta);
transformBox.translate(-transformBox.size.width / 2.0, -transformBox.size.height / 2.0);
// tester.checkFrame();
}
final bool debugDisplayList = false; // set this to true to use the test rendering logic
void main() {
// Because we're going to use UINodes, we want to initialise its
// AppView, not use the default one. We don't really need to do
@ -84,7 +80,7 @@ void main() {
// it's good practice in case we happen to not have a
// RenderObjectToUINodeAdapter in our tree at startup, or in case we
// want a renderViewOverride.
UINodeAppView.initUINodeAppView(renderViewOverride: debugDisplayList ? tester : null);
UINodeAppView.initUINodeAppView();
RenderFlex flexRoot = new RenderFlex(direction: FlexDirection.vertical);

View File

@ -45,6 +45,7 @@ dart_pkg("sdk") {
"lib/framework/components/tool_bar.dart",
"lib/framework/debug/shake-to-reload.sky",
"lib/framework/debug/tracing.dart",
"lib/framework/debug/utils.dart",
"lib/framework/editing/editable_string.dart",
"lib/framework/editing/editable_text.dart",
"lib/framework/editing/keyboard.dart",

View File

@ -0,0 +1,12 @@
final bool inDebugBuild = _initInDebugBuild();
bool _initInDebugBuild() {
bool _inDebug = false;
bool setAssert() {
_inDebug = true;
return true;
}
assert(setAssert());
return _inDebug;
}

View File

@ -4,16 +4,26 @@
import 'dart:math' as math;
import 'dart:sky' as sky;
import 'object.dart';
import '../painting/box_painter.dart';
import 'package:vector_math/vector_math.dart';
import 'package:sky/framework/net/image_cache.dart' as image_cache;
import 'package:vector_math/vector_math.dart';
import '../debug/utils.dart';
import '../painting/box_painter.dart';
import 'object.dart';
export '../painting/box_painter.dart';
// GENERIC BOX RENDERING
// Anything that has a concept of x, y, width, height is going to derive from this
// This class should only be used in debug builds
class _DebugSize extends Size {
_DebugSize(Size source, this._owner, this._canBeUsedByParent): super.copy(source);
final RenderBox _owner;
final bool _canBeUsedByParent;
}
class EdgeDims {
// used for e.g. padding
const EdgeDims(this.top, this.right, this.bottom, this.left);
@ -153,7 +163,10 @@ class BoxConstraints {
}
Size constrain(Size size) {
return new Size(constrainWidth(size.width), constrainHeight(size.height));
Size result = new Size(constrainWidth(size.width), constrainHeight(size.height));
if (size is _DebugSize)
result = new _DebugSize(result, size._owner, size._canBeUsedByParent);
return result;
}
bool get isInfinite => maxWidth >= double.INFINITY || maxHeight >= double.INFINITY;
@ -220,6 +233,24 @@ abstract class RenderBox extends RenderObject {
return constraints.constrainHeight(0.0);
}
// This whole block should only be here in debug builds
bool _debugDoingThisLayout = false;
bool _debugCanParentUseSize;
void layoutWithoutResize() {
_debugDoingThisLayout = true;
_debugCanParentUseSize = false;
super.layoutWithoutResize();
_debugCanParentUseSize = null;
_debugDoingThisLayout = false;
}
void layout(dynamic constraints, { bool parentUsesSize: false }) {
_debugDoingThisLayout = true;
_debugCanParentUseSize = parentUsesSize;
super.layout(constraints, parentUsesSize: parentUsesSize);
_debugCanParentUseSize = null;
_debugDoingThisLayout = false;
}
BoxConstraints get constraints { BoxConstraints result = super.constraints; return result; }
void performResize() {
// default behaviour for subclasses that have sizedByParent = true
@ -241,11 +272,19 @@ abstract class RenderBox extends RenderObject {
}
void hitTestChildren(HitTestResult result, { Point position }) { }
// TODO(ianh): In non-debug builds, this should all just be:
// Size size = Size.zero;
// In debug builds, however:
Size _size = Size.zero;
Size get size => _size;
void set size(Size value) {
assert(RenderObject.debugDoingLayout);
_size = value;
assert(_debugDoingThisLayout);
if (value is _DebugSize) {
assert(value._canBeUsedByParent);
assert(value._owner.parent == this);
}
_size = inDebugBuild ? new _DebugSize(value, this, _debugCanParentUseSize) : value;
}
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}size: ${size}\n';
@ -394,7 +433,7 @@ class RenderConstrainedBox extends RenderProxyBox {
void performLayout() {
if (child != null) {
child.layout(constraints.apply(_additionalConstraints));
child.layout(constraints.apply(_additionalConstraints), parentUsesSize: true);
size = child.size;
} else {
performResize();
@ -439,7 +478,7 @@ class RenderShrinkWrapWidth extends RenderProxyBox {
void performLayout() {
if (child != null) {
child.layout(_getInnerConstraints(constraints));
child.layout(_getInnerConstraints(constraints), parentUsesSize: true);
size = child.size;
} else {
performResize();
@ -663,7 +702,7 @@ class RenderPositionedBox extends RenderShiftedBox {
void performLayout() {
if (child != null) {
child.layout(constraints.loosen());
child.layout(constraints.loosen(), parentUsesSize: true);
size = constraints.constrain(child.size);
assert(child.parentData is BoxParentData);
Size delta = size - child.size;

View File

@ -128,11 +128,11 @@ abstract class RenderObject extends AbstractNode {
_nodesNeedingLayout = new List<RenderObject>();
dirtyNodes..sort((a, b) => a.depth - b.depth)..forEach((node) {
if (node._needsLayout && node.attached)
node._doLayout();
node.layoutWithoutResize();
});
_debugDoingLayout = false;
}
void _doLayout() {
void layoutWithoutResize() {
try {
assert(_relayoutSubtreeRoot == this);
performLayout();

View File

@ -211,5 +211,11 @@ class RenderParagraph extends RenderBox {
// we should probably expose a way to do precise (inter-glpyh) hit testing
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}style:\n${style.toString("$prefix ")}\n${prefix}text: ${text}\n';
String debugDescribeSettings(String prefix) {
String result = '${super.debugDescribeSettings(prefix)}';
if (style != null)
result += '${prefix}style:\n' + style.toString('$prefix ') + '\n';
result += '${prefix}text: ${text}\n';
return result;
}
}