Commit 1f40d96f authored by Hixie's avatar Hixie

Improve debugging output

Teach dumpRenderTree() to draw actual trees.
Make the TextStyle output terser so it doesn't overflow the output.
Make debugDumpApp() say what mode we're in (checked vs release).
Hide lifecycle state from release mode dumps (since it's checked-only state).
parent 6e91cfa4
......@@ -11,6 +11,7 @@ import 'dart:ui' as ui;
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/rendering.dart';
import 'stock_data.dart';
......
......@@ -112,7 +112,7 @@ class StockHomeState extends State<StockHome> {
),
new DrawerItem(
icon: 'device/dvr',
onPressed: () { debugDumpApp(); },
onPressed: () { debugDumpApp(); debugDumpRenderTree(); },
child: new Text('Dump App to Console')
),
new DrawerDivider(),
......
......@@ -252,25 +252,131 @@ class TextStyle {
List<String> result = <String>[];
if (color != null)
result.add('${prefix}color: $color');
// TODO(hansmuller): escape the fontFamily string.
if (fontFamily != null)
result.add('${prefix}fontFamily: "$fontFamily"');
result.add('${prefix}family: "$fontFamily"');
if (fontSize != null)
result.add('${prefix}fontSize: $fontSize');
if (fontWeight != null)
result.add('${prefix}fontWeight: $fontWeight');
if (fontStyle != null)
result.add('${prefix}fontStyle: $fontStyle');
if (textAlign != null)
result.add('${prefix}textAlign: $textAlign');
if (textBaseline != null)
result.add('${prefix}textBaseline: $textBaseline');
if (decoration != null)
result.add('${prefix}decoration: $decoration');
if (decorationColor != null)
result.add('${prefix}decorationColor: $decorationColor');
if (decorationStyle != null)
result.add('${prefix}decorationStyle: $decorationStyle');
result.add('${prefix}size: $fontSize');
if (fontWeight != null) {
switch (fontWeight) {
case FontWeight.w100:
result.add('${prefix}weight: 100');
break;
case FontWeight.w200:
result.add('${prefix}weight: 200');
break;
case FontWeight.w300:
result.add('${prefix}weight: 300');
break;
case FontWeight.w400:
result.add('${prefix}weight: 400');
break;
case FontWeight.w500:
result.add('${prefix}weight: 500');
break;
case FontWeight.w600:
result.add('${prefix}weight: 600');
break;
case FontWeight.w700:
result.add('${prefix}weight: 700');
break;
case FontWeight.w800:
result.add('${prefix}weight: 800');
break;
case FontWeight.w900:
result.add('${prefix}weight: 900');
break;
}
}
if (fontStyle != null) {
switch (fontStyle) {
case FontStyle.normal:
result.add('${prefix}style: normal');
break;
case FontStyle.italic:
result.add('${prefix}style: italic');
break;
}
}
if (textAlign != null) {
switch (textAlign) {
case TextAlign.left:
result.add('${prefix}align: left');
break;
case TextAlign.right:
result.add('${prefix}align: right');
break;
case TextAlign.center:
result.add('${prefix}align: center');
break;
}
}
if (textBaseline != null) {
switch (textBaseline) {
case TextBaseline.alphabetic:
result.add('${prefix}baseline: alphabetic');
break;
case TextBaseline.ideographic:
result.add('${prefix}baseline: ideographic');
break;
}
}
if (decoration != null || decorationColor != null || decorationStyle != null) {
String decorationDescription = '${prefix}decoration: ';
bool haveDecorationDescription = false;
if (decorationStyle != null) {
switch (decorationStyle) {
case TextDecorationStyle.solid:
decorationDescription += 'solid';
break;
case TextDecorationStyle.double:
decorationDescription += 'double';
break;
case TextDecorationStyle.dotted:
decorationDescription += 'dotted';
break;
case TextDecorationStyle.dashed:
decorationDescription += 'dashed';
break;
case TextDecorationStyle.wavy:
decorationDescription += 'wavy';
break;
}
haveDecorationDescription = true;
}
if (decorationColor != null) {
if (haveDecorationDescription)
decorationDescription += ' ';
decorationDescription += '$decorationColor';
haveDecorationDescription = true;
}
if (decoration != null) {
if (haveDecorationDescription)
decorationDescription += ' ';
bool multipleDecorations = false;
for (TextDecoration value in decoration) {
if (multipleDecorations)
decorationDescription += '+';
switch (value) {
case TextDecoration.none:
decorationDescription += 'none';
break;
case TextDecoration.underline:
decorationDescription += 'underline';
break;
case TextDecoration.overline:
decorationDescription += 'overline';
break;
case TextDecoration.lineThrough:
decorationDescription += 'line-through';
break;
}
multipleDecorations = true;
}
haveDecorationDescription = true;
}
assert(haveDecorationDescription);
result.add(decorationDescription);
}
if (result.isEmpty)
return '$prefix<no style specified>';
return result.join('\n');
......
......@@ -1139,11 +1139,18 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
/// Returns a description of the tree rooted at this node.
/// If the prefix argument is provided, then every line in the output
/// will be prefixed by that string.
String toStringDeep([String prefix = '']) {
String toStringDeep([String prefixLineOne = '', String prefixOtherLines = '']) {
RenderObject debugPreviousActiveLayout = _debugActiveLayout;
_debugActiveLayout = null;
prefix += ' ';
String result = '$this\n${debugDescribeSettings(prefix)}${debugDescribeChildren(prefix)}';
String result = '$prefixLineOne$this\n';
final String childrenDescription = debugDescribeChildren(prefixOtherLines);
final String settingsPrefix = childrenDescription != '' ? '$prefixOtherLines \u2502 ' : '$prefixOtherLines ';
result += debugDescribeSettings(settingsPrefix);
if (childrenDescription != '')
result += '$prefixOtherLines \u2502\n';
else
result += '$prefixOtherLines\n';
result += childrenDescription;
_debugActiveLayout = debugPreviousActiveLayout;
return result;
}
......@@ -1198,7 +1205,7 @@ abstract class RenderObjectWithChildMixin<ChildType extends RenderObject> implem
}
String debugDescribeChildren(String prefix) {
if (child != null)
return '${prefix}child: ${child.toStringDeep(prefix)}';
return '${child.toStringDeep("$prefix \u2514\u2500child: ", "$prefix ")}';
return '';
}
}
......@@ -1442,14 +1449,20 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
String debugDescribeChildren(String prefix) {
String result = '';
int count = 1;
if (_firstChild != null) {
ChildType child = _firstChild;
while (child != null) {
result += '${prefix}child $count: ${child.toStringDeep(prefix)}';
int count = 1;
while (child != _lastChild) {
result += '${child.toStringDeep("$prefix \u251C\u2500child $count: ", "$prefix \u2502")}';
count += 1;
final ParentDataType childParentData = child.parentData;
child = childParentData.nextSibling;
}
if (child != null) {
assert(child == _lastChild);
result += '${child.toStringDeep("$prefix \u2514\u2500child $count: ", "$prefix ")}';
}
}
return result;
}
}
......@@ -883,6 +883,7 @@ class FractionalOffset {
value = 37 * value + y.hashCode;
return value;
}
String toString() => '$runtimeType($x, $y)';
}
/// Applies a transformation before painting its child
......@@ -1016,7 +1017,7 @@ class RenderTransform extends RenderProxyBox {
String debugDescribeSettings(String prefix) {
List<String> result = _transform.toString().split('\n').map((String s) => '$prefix $s\n').toList();
result.removeLast();
return '${super.debugDescribeSettings(prefix)}${prefix}transform matrix:\n${result.join()}\n${prefix}origin: $origin\n';
return '${super.debugDescribeSettings(prefix)}${prefix}transform matrix:\n${result.join()}\n${prefix}origin: $origin\nalignment: $alignment\n';
}
}
......
......@@ -92,6 +92,9 @@ void runApp(Widget app) {
void debugDumpApp() {
assert(WidgetFlutterBinding.instance != null);
assert(WidgetFlutterBinding.instance.renderViewElement != null);
String mode = 'RELEASE MODE';
assert(() { mode = 'CHECKED MODE'; return true; });
print('${WidgetFlutterBinding.instance.runtimeType} - $mode');
WidgetFlutterBinding.instance.renderViewElement.toStringDeep().split('\n').forEach(print);
}
......
......@@ -394,8 +394,11 @@ abstract class State<T extends StatefulComponent> {
void debugFillDescription(List<String> description) {
description.add('$hashCode');
assert(() {
if (_debugLifecycleState != _StateLifecycle.ready)
description.add('$_debugLifecycleState');
return true;
});
if (_config == null)
description.add('no config');
if (_element == null)
......@@ -829,9 +832,7 @@ abstract class Element<T extends Widget> implements BuildContext {
String toStringDeep([String prefixLineOne = '', String prefixOtherLines = '']) {
String result = '$prefixLineOne$this\n';
List<Element> children = <Element>[];
visitChildren((Element child) {
children.add(child);
});
visitChildren(children.add);
if (children.length > 0) {
Element last = children.removeLast();
for (Element child in children)
......
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