Commit 9f510ebd authored by Jacob Richman's avatar Jacob Richman Committed by GitHub

Refactor RenderObject.toStringDeep and Widget.toStringDeep code to use DiagnosticsNode (#11359)

Refactor RenderObject.toStringDeep and Widget.toStringDeep code to use DiagnosticsNode.
parent 5278588d
......@@ -102,10 +102,10 @@ class _StatusBarPaddingSliver extends SingleChildRenderObjectWidget {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('maxHeight: $maxHeight');
description.add('scrollFactor: $scrollFactor');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DoubleProperty('maxHeight', maxHeight));
description.add(new DoubleProperty('scrollFactor', scrollFactor));
}
}
......
......@@ -101,10 +101,9 @@ class CupertinoButton extends StatefulWidget {
_CupertinoButtonState createState() => new _CupertinoButtonState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (!enabled)
description.add('disabled');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new FlagProperty('enabled', value: enabled, ifFalse: 'disabled'));
}
}
......
......@@ -422,6 +422,22 @@ class _CupertinoEdgeShadowDecoration extends Decoration {
int get hashCode {
return edgeGradient.hashCode;
}
@override
DiagnosticsNode toDiagnosticsNode({
String name,
DiagnosticsTreeStyle style: DiagnosticsTreeStyle.singleLine,
}) {
return new DiagnosticsNode.lazy(
name: name,
object: this,
style: style,
description: '$runtimeType',
fillProperties: (List<DiagnosticsNode> properties) {
properties.add(new DiagnosticsProperty<LinearGradient>('edgeGradient', edgeGradient));
},
);
}
}
/// A [BoxPainter] used to draw the page transition shadow using gradients.
......
......@@ -111,11 +111,11 @@ class CupertinoSlider extends StatefulWidget {
_CupertinoSliderState createState() => new _CupertinoSliderState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('value: ${value.toStringAsFixed(1)}');
description.add('min: $min');
description.add('max: $max');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DoubleProperty('value', value));
description.add(new DoubleProperty('min', min));
description.add(new DoubleProperty('max', max));
}
}
......
......@@ -88,11 +88,10 @@ class CupertinoSwitch extends StatefulWidget {
_CupertinoSwitchState createState() => new _CupertinoSwitchState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('value: ${value ? "on" : "off"}');
if (onChanged == null)
description.add('disabled');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new FlagProperty('value', value: value, ifTrue: 'on', ifFalse: 'off', showName: true));
description.add(new ObjectFlagProperty<ValueChanged<bool>>('onChanged', onChanged, ifNull: 'disabled'));
}
}
......@@ -420,10 +419,9 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox implements SemanticsAc
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('value: ${value ? "checked" : "unchecked"}');
if (!isInteractive)
description.add('disabled');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new FlagProperty('value', value: value, ifTrue: 'checked', ifFalse: 'unchecked', showName: true));
description.add(new FlagProperty('isInteractive', value: isInteractive, ifTrue: 'enabled', ifFalse: 'disabled', showName: true, defaultValue: true));
}
}
......@@ -249,10 +249,9 @@ class MaterialButton extends StatefulWidget {
_MaterialButtonState createState() => new _MaterialButtonState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (!enabled)
description.add('disabled');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new FlagProperty('enabled', value: enabled, ifFalse: 'disabled'));
}
}
......
......@@ -203,12 +203,10 @@ class IconButton extends StatelessWidget {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('$icon');
if (onPressed == null)
description.add('disabled');
if (tooltip != null)
description.add('tooltip: "$tooltip"');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<Widget>('icon', icon, showName: false));
description.add(new ObjectFlagProperty<VoidCallback>('onPressed', onPressed, ifNull: 'disabled'));
description.add(new StringProperty('tooltip', tooltip, defaultValue: null, quoted: false));
}
}
......@@ -222,8 +222,8 @@ class InkResponse extends StatefulWidget {
_InkResponseState<InkResponse> createState() => new _InkResponseState<InkResponse>();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
final List<String> gestures = <String>[];
if (onTap != null)
gestures.add('tap');
......@@ -233,8 +233,14 @@ class InkResponse extends StatefulWidget {
gestures.add('long press');
if (gestures.isEmpty)
gestures.add('<none>');
description.add('gestures: ${gestures.join(", ")}');
description.add('${containedInkWell ? "clipped to " : ""}$highlightShape');
description.add(new IterableProperty<String>('gestures', gestures));
description.add(new DiagnosticsProperty<bool>('containedInkWell', containedInkWell, hidden: true));
description.add(new DiagnosticsProperty<BoxShape>(
'highlightShape',
highlightShape,
description: '${containedInkWell ? "clipped to " : ""}$highlightShape',
showName: false,
));
}
}
......
......@@ -372,12 +372,12 @@ class InputDecorator extends StatelessWidget {
final Widget child;
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('decoration: $decoration');
description.add('baseStyle: $baseStyle');
description.add('isFocused: $isFocused');
description.add('isEmpty: $isEmpty');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<InputDecoration>('decoration', decoration));
description.add(new EnumProperty<TextStyle>('baseStyle', baseStyle));
description.add(new DiagnosticsProperty<bool>('isFocused', isFocused));
description.add(new DiagnosticsProperty<bool>('isEmpty', isEmpty));
}
Color _getActiveColor(ThemeData themeData) {
......@@ -615,9 +615,9 @@ class _AnimatedLabel extends ImplicitlyAnimatedWidget {
_AnimatedLabelState createState() => new _AnimatedLabelState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
'$style'.split('\n').forEach(description.add);
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
style?.debugFillProperties(description);
}
}
......
......@@ -175,18 +175,13 @@ class Material extends StatefulWidget {
_MaterialState createState() => new _MaterialState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('$type');
description.add('elevation: ${elevation.toStringAsFixed(1)}');
if (color != null)
description.add('color: $color');
if (textStyle != null) {
for (String entry in '$textStyle'.split('\n'))
description.add('textStyle.$entry');
}
if (borderRadius != null)
description.add('borderRadius: $borderRadius');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new EnumProperty<MaterialType>('type', type));
description.add(new DoubleProperty('elevation', elevation));
description.add(new DiagnosticsProperty<Color>('color', color, defaultValue: null));
textStyle?.debugFillProperties(description, prefix: 'textStyle.');
description.add(new EnumProperty<BorderRadius>('borderRadius', borderRadius, defaultValue: null));
}
/// The default radius of an ink splash in logical pixels.
......
......@@ -4,6 +4,7 @@
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'material.dart';
......@@ -60,13 +61,9 @@ abstract class ProgressIndicator extends StatefulWidget {
Color _getValueColor(BuildContext context) => valueColor?.value ?? Theme.of(context).accentColor;
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (value != null) {
description.add('${(value.clamp(0.0, 1.0) * 100.0).toStringAsFixed(1)}%');
} else {
description.add('<indeterminate>');
}
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new PercentProperty('value', value, showName: false, ifNull: '<indeterminate>'));
}
}
......
......@@ -161,11 +161,11 @@ class Slider extends StatefulWidget {
_SliderState createState() => new _SliderState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('value: ${value.toStringAsFixed(1)}');
description.add('min: $min');
description.add('max: $max');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DoubleProperty('value', value));
description.add(new DoubleProperty('min', min));
description.add(new DoubleProperty('max', max));
}
}
......
......@@ -99,11 +99,10 @@ class Switch extends StatefulWidget {
_SwitchState createState() => new _SwitchState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('value: ${value ? "on" : "off"}');
if (onChanged == null)
description.add('disabled');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new FlagProperty('value', value: value, ifTrue: 'on', ifFalse: 'off', showName: true));
description.add(new ObjectFlagProperty<ValueChanged<bool>>('onChanged', onChanged, ifNull: 'disabled'));
}
}
......
......@@ -89,12 +89,10 @@ class Tab extends StatelessWidget {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (text != null)
description.add('text: $text');
if (icon != null)
description.add('icon: $icon');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new StringProperty('text', text, defaultValue: null));
description.add(new DiagnosticsProperty<Widget>('icon', icon, defaultValue: null));
}
}
......
......@@ -176,25 +176,17 @@ class TextField extends StatefulWidget {
_TextFieldState createState() => new _TextFieldState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (controller != null)
description.add('controller: $controller');
if (focusNode != null)
description.add('focusNode: $focusNode');
description.add('decoration: $decoration');
if (keyboardType != TextInputType.text)
description.add('keyboardType: $keyboardType');
if (style != null)
description.add('style: $style');
if (autofocus)
description.add('autofocus: $autofocus');
if (obscureText)
description.add('obscureText: $obscureText');
if (autocorrect)
description.add('autocorrect: $autocorrect');
if (maxLines != 1)
description.add('maxLines: $maxLines');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<TextEditingController>('controller', controller, defaultValue: null));
description.add(new DiagnosticsProperty<FocusNode>('focusNode', focusNode, defaultValue: null));
description.add(new DiagnosticsProperty<InputDecoration>('decoration', decoration));
description.add(new EnumProperty<TextInputType>('keyboardType', keyboardType, defaultValue: TextInputType.text));
description.add(new DiagnosticsProperty<TextStyle>('style', style, defaultValue: null));
description.add(new DiagnosticsProperty<bool>('autofocus', autofocus, defaultValue: false));
description.add(new DiagnosticsProperty<bool>('obscureText', obscureText, defaultValue: false));
description.add(new DiagnosticsProperty<bool>('autocorrect', autocorrect, defaultValue: false));
description.add(new IntProperty('maxLines', maxLines, defaultValue: 1));
}
}
......
......@@ -138,9 +138,9 @@ class Theme extends StatelessWidget {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('$data');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<ThemeData>('data', data, showName: false));
}
}
......@@ -235,9 +235,8 @@ class _AnimatedThemeState extends AnimatedWidgetBaseState<AnimatedTheme> {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (_data != null)
description.add('$_data');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<ThemeDataTween>('data', _data, showName: false, defaultValue: null));
}
}
......@@ -303,10 +303,9 @@ abstract class RenderToggleable extends RenderConstrainedBox implements Semantic
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('value: ${value ? "checked" : "unchecked"}');
if (!isInteractive)
description.add('disabled');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new FlagProperty('value', value: value, ifTrue: 'checked', ifFalse: 'unchecked', showName: true));
description.add(new FlagProperty('isInteractive', value: isInteractive, ifTrue: 'enabled', ifFalse: 'disabled', defaultValue: true));
}
}
......@@ -86,11 +86,11 @@ class Tooltip extends StatefulWidget {
_TooltipState createState() => new _TooltipState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('"$message"');
description.add('vertical offset: $verticalOffset');
description.add('position: ${preferBelow ? "below" : "above"}');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new StringProperty('message', message, showName: false));
description.add(new DoubleProperty('vertical offset', verticalOffset));
description.add(new FlagProperty('position', value: preferBelow, ifTrue: 'below', ifFalse: 'above', showName: true));
}
}
......
......@@ -1601,38 +1601,24 @@ class BoxDecoration extends Decoration {
);
}
/// Stringifies the BoxDecoration. By default, the output will be on one line.
/// If the method is passed a non-empty string argument, then the output will
/// span multiple lines, each prefixed by that argument.
@override
String toString([String prefix = '', String indentPrefix]) {
final List<String> result = <String>[];
if (color != null)
result.add('${prefix}color: $color');
if (image != null)
result.add('${prefix}image: $image');
if (border != null)
result.add('${prefix}border: $border');
if (borderRadius != null)
result.add('${prefix}borderRadius: $borderRadius');
if (boxShadow != null) {
if (indentPrefix != null && boxShadow.length > 1) {
result.add('${prefix}boxShadow:');
for (BoxShadow shadow in boxShadow)
result.add('$indentPrefix$shadow');
} else {
result.add('${prefix}boxShadow: ${boxShadow.map((BoxShadow shadow) => shadow.toString()).join(", ")}');
}
}
if (gradient != null)
result.add('${prefix}gradient: $gradient');
if (shape != BoxShape.rectangle)
result.add('${prefix}shape: $shape');
if (prefix == '')
return '$runtimeType(${result.join(', ')})';
if (result.isEmpty)
return '$prefix<no decorations specified>';
return result.join('\n');
DiagnosticsNode toDiagnosticsNode({ String name, DiagnosticsTreeStyle style: DiagnosticsTreeStyle.whitespace }) {
return new DiagnosticsNode.lazy(
name: name,
object: this,
description: '',
style: style,
emptyBodyDescription: '<no decorations specified>',
fillProperties: (List<DiagnosticsNode> properties) {
properties.add(new DiagnosticsProperty<Color>('color', color, defaultValue: null));
properties.add(new DiagnosticsProperty<DecorationImage>('image', image, defaultValue: null));
properties.add(new DiagnosticsProperty<Border>('border', border, defaultValue: null));
properties.add(new DiagnosticsProperty<BorderRadius>('borderRadius', borderRadius, defaultValue: null));
properties.add(new IterableProperty<BoxShadow>('boxShadow', boxShadow, defaultValue: null, style: style));
properties.add(new DiagnosticsProperty<Gradient>('gradient', gradient, defaultValue: null));
properties.add(new EnumProperty<BoxShape>('shape', shape, defaultValue: BoxShape.rectangle));
},
);
}
@override
......
......@@ -25,7 +25,7 @@ export 'edge_insets.dart' show EdgeInsets;
/// shared between boxes; [BoxPainter] objects can cache resources to
/// make painting on a particular surface faster.
@immutable
abstract class Decoration {
abstract class Decoration extends TreeDiagnostics {
/// Abstract const constructor. This constructor enables subclasses to provide
/// const constructors so that they can be used in const expressions.
const Decoration();
......@@ -81,16 +81,10 @@ abstract class Decoration {
/// if it is a [BoxDecoration] with definitely no [DecorationImage]).
BoxPainter createBoxPainter([VoidCallback onChanged]);
/// Returns a string representation of this object.
///
/// Every line of the output should be prefixed by `prefix`.
///
/// If `indentPrefix` is non-null, then the description can be further split
/// into sublines, and each subline should be prefixed with `indentPrefix`
/// (rather that `prefix`). This is used, for example, by [BoxDecoration] for
/// the otherwise quite verbose [BoxShadow] descriptions.
@override
String toString([String prefix = '', String indentPrefix ]) => '$prefix$runtimeType';
String toString() {
return toDiagnosticsNode(style: DiagnosticsTreeStyle.singleLine).toStringDeep();
}
}
/// A stateful class that can paint a particular [Decoration].
......
......@@ -7,6 +7,7 @@ import 'dart:typed_data';
import 'dart:ui' as ui show Gradient, TextBox, lerpDouble;
import 'package:flutter/services.dart';
import 'package:flutter/foundation.dart';
import 'basic_types.dart';
import 'box_fit.dart';
......@@ -210,9 +211,19 @@ class FlutterLogoDecoration extends Decoration {
}
@override
String toString([String prefix = '', String prefixIndent ]) {
final String extra = _inTransition ? ', transition $_position:$_opacity' : '';
return '$prefix$runtimeType($lightColor/$darkColor on $textColor, $style$extra)';
DiagnosticsNode toDiagnosticsNode({ String name, DiagnosticsTreeStyle style }) {
return new DiagnosticsNode.lazy(
name: name,
description: '$runtimeType',
object: this,
style: style,
fillProperties: (List<DiagnosticsNode> properties) {
properties.add(new DiagnosticsNode.message('$lightColor/$darkColor on $textColor'));
properties.add(new EnumProperty<FlutterLogoStyle>('style', this.style));
if (_inTransition)
properties.add(new DiagnosticsNode.message('transition $_position:$_opacity'));
}
);
}
}
......
......@@ -47,7 +47,7 @@ import 'text_style.dart';
/// * [RichText], a widget for finer control of text rendering.
/// * [TextPainter], a class for painting [TextSpan] objects on a [Canvas].
@immutable
class TextSpan {
class TextSpan implements TreeDiagnostics {
/// Creates a [TextSpan] with the given values.
///
/// For the object to be useful, at least one of [text] or
......@@ -250,27 +250,7 @@ class TextSpan {
@override
String toString([String prefix = '']) {
final StringBuffer buffer = new StringBuffer();
buffer.writeln('$prefix$runtimeType:');
final String indent = '$prefix ';
if (style != null)
buffer.writeln(style.toString(indent));
if (recognizer != null)
buffer.writeln('${indent}recognizer: ${recognizer.runtimeType}');
if (text != null)
buffer.writeln('$indent"$text"');
if (children != null) {
for (TextSpan child in children) {
if (child != null) {
buffer.write(child.toString(indent));
} else {
buffer.writeln('$indent<null>');
}
}
}
if (style == null && text == null && children == null)
buffer.writeln('$indent(empty)');
return buffer.toString();
return toStringDeep(prefix, prefix);
}
/// In checked mode, throws an exception if the object is not in a
......@@ -337,6 +317,11 @@ class TextSpan {
return result;
}
@override
String toStringDeep([String prefixLineOne = '', String prefixOtherLines = '']) {
return toDiagnosticsNode().toStringDeep(prefixLineOne, prefixOtherLines);
}
@override
bool operator ==(dynamic other) {
if (identical(this, other))
......@@ -352,4 +337,37 @@ class TextSpan {
@override
int get hashCode => hashValues(style, text, recognizer, hashList(children));
@override
DiagnosticsNode toDiagnosticsNode({
String name,
DiagnosticsTreeStyle style: DiagnosticsTreeStyle.whitespace,
}) {
return new DiagnosticsNode.lazy(
name: name,
object: this,
description: '$runtimeType',
style: style,
fillProperties: (List<DiagnosticsNode> properties) {
// Properties on style are added as if they were properties directly on
// this TextSpan.
if (this.style != null)
this.style.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<GestureRecognizer>(
'recognizer', recognizer,
description: recognizer?.runtimeType?.toString(),
defaultValue: null,
));
properties.add(new StringProperty('text', text, showName: false, defaultValue: null));
if (this.style == null && text == null && children == null)
properties.add(new DiagnosticsNode.message('(empty)'));
},
getChildren: () {
return children == null ?
<DiagnosticsNode>[] :
children.map((TextSpan child) => child?.toDiagnosticsNode()).toList();
},
);
}
}
......@@ -131,7 +131,7 @@ import 'basic_types.dart';
/// * [TextSpan], the class that wraps a [TextStyle] for the purposes of
/// passing it to a [RichText].
@immutable
class TextStyle {
class TextStyle extends TreeDiagnostics {
/// Creates a text style.
const TextStyle({
this.inherit: true,
......@@ -456,112 +456,100 @@ class TextStyle {
}
@override
String toString([String prefix = '']) {
final List<String> result = <String>[];
result.add('${prefix}inherit: $inherit');
if (color != null)
result.add('${prefix}color: $color');
if (fontFamily != null)
result.add('${prefix}family: "$fontFamily"');
if (fontSize != null)
result.add('${prefix}size: $fontSize');
DiagnosticsNode toDiagnosticsNode({
String name,
DiagnosticsTreeStyle style: DiagnosticsTreeStyle.singleLine,
}) {
return new DiagnosticsNode.lazy(
name: name,
object: this,
style: style,
description: '$runtimeType',
fillProperties: debugFillProperties,
);
}
@override
String toString() => toDiagnosticsNode().toString();
/// Adds all properties prefixing property names with the optional `prefix`.
void debugFillProperties(List<DiagnosticsNode> properties, { String prefix: '' }) {
final List<DiagnosticsNode> styles = <DiagnosticsNode>[];
styles.add(new DiagnosticsProperty<Color>('${prefix}color', color, defaultValue: null));
styles.add(new StringProperty('${prefix}family', fontFamily, defaultValue: null, quoted: false));
styles.add(new DoubleProperty('${prefix}size', fontSize, defaultValue: null));
String weightDescription;
if (fontWeight != null) {
switch (fontWeight) {
case FontWeight.w100:
result.add('${prefix}weight: 100');
weightDescription = '100';
break;
case FontWeight.w200:
result.add('${prefix}weight: 200');
weightDescription = '200';
break;
case FontWeight.w300:
result.add('${prefix}weight: 300');
weightDescription = '300';
break;
case FontWeight.w400:
result.add('${prefix}weight: 400');
weightDescription = '400';
break;
case FontWeight.w500:
result.add('${prefix}weight: 500');
weightDescription = '500';
break;
case FontWeight.w600:
result.add('${prefix}weight: 600');
weightDescription = '600';
break;
case FontWeight.w700:
result.add('${prefix}weight: 700');
weightDescription = '700';
break;
case FontWeight.w800:
result.add('${prefix}weight: 800');
weightDescription = '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 (letterSpacing != null)
result.add('${prefix}letterSpacing: ${letterSpacing}x');
if (wordSpacing != null)
result.add('${prefix}wordSpacing: ${wordSpacing}x');
if (textBaseline != null) {
switch (textBaseline) {
case TextBaseline.alphabetic:
result.add('${prefix}baseline: alphabetic');
break;
case TextBaseline.ideographic:
result.add('${prefix}baseline: ideographic');
weightDescription = '900';
break;
}
}
if (height != null)
result.add('${prefix}height: ${height}x');
// TODO(jacobr): switch this to use enumProperty which will either cause the
// weight description to change to w600 from 600 or require existing
// enumProperty to handle this special case.
styles.add(new DiagnosticsProperty<FontWeight>(
'${prefix}weight',
fontWeight,
description: weightDescription,
defaultValue: null,
));
styles.add(new EnumProperty<FontStyle>('${prefix}style', fontStyle, defaultValue: null));
styles.add(new DoubleProperty('${prefix}letterSpacing', letterSpacing, unit: 'x', defaultValue: null));
styles.add(new DoubleProperty('${prefix}wordSpacing', wordSpacing, unit: 'x', defaultValue: null));
styles.add(new EnumProperty<TextBaseline>('${prefix}baseline', textBaseline, defaultValue: null));
styles.add(new DoubleProperty('${prefix}height', height, unit: 'x', defaultValue: null));
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 += ' ';
decorationDescription += '$decoration';
haveDecorationDescription = true;
}
assert(haveDecorationDescription);
result.add(decorationDescription);
final List<String> decorationDescription = <String>[];
if (decorationStyle != null)
decorationDescription.add(describeEnum((decorationStyle)));
// Hide decorationColor from the default text view as it is shown in the
// terse decoration summary as well.
styles.add(new DiagnosticsProperty<Color>('${prefix}decorationColor', decorationColor, defaultValue: null, hidden: true));
if (decorationColor != null)
decorationDescription.add('$decorationColor');
// Intentionally collide with the property 'decoration' added below.
// Tools that show hidden properties could choose the first property
// matching the name to disambiguate.
styles.add(new DiagnosticsProperty<TextDecoration>('${prefix}decoration', decoration, defaultValue: null, hidden: true));
if (decoration != null)
decorationDescription.add('$decoration');
assert(decorationDescription.isNotEmpty);
styles.add(new MessageProperty('${prefix}decoration', decorationDescription.join(' ')));
}
if (result.isEmpty)
return '$prefix<no style specified>';
return result.join('\n');
final bool styleSpecified = styles.any((DiagnosticsNode n) => !n.hidden);
properties.add(new DiagnosticsProperty<bool>('${prefix}inherit', inherit, hidden: !styleSpecified && inherit));
properties.addAll(styles);
if (!styleSpecified)
properties.add(new FlagProperty('inherit', value: inherit, ifTrue: '$prefix<all styles inherited>', ifFalse: '$prefix<no style specified>'));
}
}
......@@ -156,9 +156,9 @@ class RenderListBody extends RenderBox
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('mainAxis: $mainAxis');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new EnumProperty<Axis>('mainAxis', mainAxis));
}
double _getIntrinsicCrossAxis(_ChildSizingFunction childSize) {
......
......@@ -836,9 +836,8 @@ class _IntrinsicDimensionsCacheEntry {
/// * Implement the [visitChildren] method such that it calls its argument for
/// each child, typically in paint order (back-most to front-most).
///
/// * Implement [debugDescribeChildren] such that it outputs a string that
/// describes all the children. In principle, for each child you want to
/// include the results of that child's [toStringDeep] function.
/// * Implement [debugDescribeChildren] such that it outputs a [DiagnosticNode]
/// for each child.
///
/// Implementing these seven bullet points is essentially all that the two
/// aforementioned mixins do.
......@@ -1667,22 +1666,17 @@ abstract class RenderBox extends RenderObject {
while (!node.constraints.hasBoundedWidth && node.parent is RenderBox)
node = node.parent;
information.writeln('The nearest ancestor providing an unbounded width constraint is:');
information.writeln(' $node');
final List<String> description = <String>[];
node.debugFillDescription(description);
for (String line in description)
information.writeln(' $line');
}
information.write(' ');
information.writeln(node.toStringShallow('\n '));
}
if (!constraints.hasBoundedHeight) {
RenderBox node = this;
while (!node.constraints.hasBoundedHeight && node.parent is RenderBox)
node = node.parent;
information.writeln('The nearest ancestor providing an unbounded height constraint is:');
information.writeln(' $node');
final List<String> description = <String>[];
node.debugFillDescription(description);
for (String line in description)
information.writeln(' $line');
information.write(' ');
information.writeln(node.toStringShallow('\n '));
}
throw new FlutterError(
'$runtimeType object was given an infinite size during layout.\n'
......@@ -2094,9 +2088,9 @@ abstract class RenderBox extends RenderObject {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('size: ${ hasSize ? size : "MISSING" }');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<Size>('size', _size, ifNull: 'MISSING'));
}
}
......
......@@ -156,7 +156,7 @@ bool debugProfilePaintsEnabled = false;
/// Returns a list of strings representing the given transform in a format
/// useful for [RenderObject.debugFillDescription].
/// useful for [TransformProperty].
///
/// If the argument is null, returns a list with the single string "null".
List<String> debugDescribeTransform(Matrix4 transform) {
......@@ -167,6 +167,20 @@ List<String> debugDescribeTransform(Matrix4 transform) {
return matrix;
}
/// Property which handles [Matrix4] that represent transforms.
class TransformProperty extends DiagnosticsProperty<Matrix4> {
TransformProperty(String name, Matrix4 value, {
Object defaultValue: kNoDefaultValue,
}) : super(
name,
value,
defaultValue: defaultValue,
);
@override
String valueToString() => debugDescribeTransform(value).join('\n');
}
void _debugDrawDoubleRect(Canvas canvas, Rect outerRect, Rect innerRect, Color color) {
final Path path = new Path()
..fillType = PathFillType.evenOdd
......
......@@ -546,22 +546,24 @@ class RenderEditable extends RenderBox {
Rect describeApproximatePaintClip(RenderObject child) => _hasVisualOverflow ? Offset.zero & size : null;
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('cursorColor: $cursorColor');
description.add('showCursor: $showCursor');
description.add('maxLines: $maxLines');
description.add('selectionColor: $selectionColor');
description.add('textScaleFactor: $textScaleFactor');
description.add('selection: $selection');
description.add('offset: $offset');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<Color>('cursorColor', cursorColor));
description.add(new DiagnosticsProperty<ValueNotifier<bool>>('showCursor', showCursor));
description.add(new IntProperty('maxLines', maxLines));
description.add(new DiagnosticsProperty<Color>('selectionColor', selectionColor));
description.add(new DoubleProperty('textScaleFactor', textScaleFactor));
description.add(new DiagnosticsProperty<TextSelection>('selection', selection));
description.add(new DiagnosticsProperty<ViewportOffset>('offset', offset));
}
@override
String debugDescribeChildren(String prefix) {
return '$prefix \u2558\u2550\u2566\u2550\u2550 text \u2550\u2550\u2550\n'
'${text.toString("$prefix \u2551 ")}' // TextSpan includes a newline
'$prefix \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n'
'${prefix.trimRight()}\n';
List<DiagnosticsNode> debugDescribeChildren() {
return <DiagnosticsNode>[
text.toDiagnosticsNode(
name: 'text',
style: DiagnosticsTreeStyle.transition,
),
];
}
}
......@@ -490,9 +490,9 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
if (node != null) {
information.writeln('The nearest ancestor providing an unbounded width constraint is:');
information.writeln(' $node');
final List<String> description = <String>[];
node.debugFillDescription(description);
for (String line in description)
final List<DiagnosticsNode> description = <DiagnosticsNode>[];
node.debugFillProperties(description);
for (DiagnosticsNode line in description)
information.writeln(' $line');
}
information.writeln('See also: https://flutter.io/layout/');
......@@ -784,13 +784,13 @@ class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, Fl
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('direction: $_direction');
description.add('mainAxisAlignment: $_mainAxisAlignment');
description.add('mainAxisSize: $_mainAxisSize');
description.add('crossAxisAlignment: $_crossAxisAlignment');
description.add('textBaseline: $_textBaseline');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new EnumProperty<Axis>('direction', _direction));
description.add(new EnumProperty<MainAxisAlignment>('mainAxisAlignment', _mainAxisAlignment));
description.add(new EnumProperty<MainAxisSize>('mainAxisSize', _mainAxisSize));
description.add(new EnumProperty<CrossAxisAlignment>('crossAxisAlignment', _crossAxisAlignment));
description.add(new EnumProperty<TextBaseline>('textBaseline', _textBaseline));
}
}
......@@ -259,26 +259,17 @@ class RenderImage extends RenderBox {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('image: $image');
if (width != null)
description.add('width: $width');
if (height != null)
description.add('height: $height');
if (scale != 1.0)
description.add('scale: $scale');
if (color != null)
description.add('color: $color');
if (colorBlendMode != null)
description.add('colorBlendMode: $colorBlendMode');
if (fit != null)
description.add('fit: $fit');
if (alignment != null)
description.add('alignment: $alignment');
if (repeat != ImageRepeat.noRepeat)
description.add('repeat: $repeat');
if (centerSlice != null)
description.add('centerSlice: $centerSlice');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<ui.Image>('image', image));
description.add(new DoubleProperty('width', width, defaultValue: null));
description.add(new DoubleProperty('height', height, defaultValue: null));
description.add(new DoubleProperty('scale', scale, defaultValue: 1.0));
description.add(new DiagnosticsProperty<Color>('color', color, defaultValue: null));
description.add(new EnumProperty<BlendMode>('colorBlendMode', colorBlendMode, defaultValue: null));
description.add(new EnumProperty<BoxFit>('fit', fit, defaultValue: null));
description.add(new DiagnosticsProperty<FractionalOffset>('alignment', alignment, defaultValue: null));
description.add(new EnumProperty<ImageRepeat>('repeat', repeat, defaultValue: ImageRepeat.noRepeat));
description.add(new DiagnosticsProperty<Rect>('centerSlice', centerSlice, defaultValue: null));
}
}
......@@ -105,12 +105,10 @@ abstract class Layer extends AbstractNode with TreeDiagnosticsMixin {
String toString() => '${super.toString()}${ owner == null ? " DETACHED" : ""}';
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (parent == null && owner != null)
description.add('owner: $owner');
if (debugCreator != null)
description.add('creator: $debugCreator');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<Object>('owner', owner, hidden: parent != null, defaultValue: null));
description.add(new DiagnosticsProperty<dynamic>('creator', debugCreator, defaultValue: null));
}
}
......@@ -164,9 +162,9 @@ class PictureLayer extends Layer {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('paint bounds: $canvasBounds');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<Rect>('paint bounds', canvasBounds));
}
}
......@@ -414,24 +412,20 @@ class ContainerLayer extends Layer {
}
@override
String debugDescribeChildren(String prefix) {
List<DiagnosticsNode> debugDescribeChildren() {
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
if (firstChild == null)
return '';
final StringBuffer result = new StringBuffer()
..write(prefix)
..write(' \u2502\n');
return children;
Layer child = firstChild;
int count = 1;
while (child != lastChild) {
result.write(child.toStringDeep("$prefix \u251C\u2500child $count: ", "$prefix \u2502"));
while (true) {
children.add(child.toDiagnosticsNode(name: 'child $count'));
if (child == lastChild)
break;
count += 1;
child = child.nextSibling;
}
if (child != null) {
assert(child == lastChild);
result.write(child.toStringDeep("$prefix \u2514\u2500child $count: ", "$prefix "));
}
return result.toString();
return children;
}
}
......@@ -466,9 +460,9 @@ class OffsetLayer extends ContainerLayer {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('offset: $offset');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<Offset>('offset', offset));
}
}
......@@ -494,9 +488,9 @@ class ClipRectLayer extends ContainerLayer {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('clipRect: $clipRect');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<Rect>('clipRect', clipRect));
}
}
......@@ -522,9 +516,9 @@ class ClipRRectLayer extends ContainerLayer {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('clipRRect: $clipRRect');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<RRect>('clipRRect', clipRRect));
}
}
......@@ -550,9 +544,9 @@ class ClipPathLayer extends ContainerLayer {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('clipPath: $clipPath');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<Path>('clipPath', clipPath));
}
}
......@@ -602,10 +596,9 @@ class TransformLayer extends OffsetLayer {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('transform:');
description.addAll(debugDescribeTransform(transform));
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new TransformProperty('transform', transform));
}
}
......@@ -634,9 +627,9 @@ class OpacityLayer extends ContainerLayer {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('alpha: $alpha');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new IntProperty('alpha', alpha));
}
}
......@@ -674,11 +667,11 @@ class ShaderMaskLayer extends ContainerLayer {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('shader: $shader');
description.add('maskRect: $maskRect');
description.add('blendMode: $blendMode');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<Shader>('shader', shader));
description.add(new DiagnosticsProperty<Rect>('maskRect', maskRect));
description.add(new DiagnosticsProperty<BlendMode>('blendMode', blendMode));
}
}
......@@ -752,11 +745,11 @@ class PhysicalModelLayer extends ContainerLayer {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('clipRRect: $clipRRect');
description.add('elevation: $elevation');
description.add('color: $color');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<RRect>('clipRRect', clipRRect));
description.add(new DoubleProperty('elevation', elevation));
description.add(new DiagnosticsProperty<Color>('color', color));
}
}
......@@ -778,7 +771,7 @@ class LayerLink {
LeaderLayer _leader;
@override
String toString() => '$runtimeType#$hashCode(${ _leader != null ? "<linked>" : "<dangling>" })';
String toString() => '${describeIdentity(this)}(${ _leader != null ? "<linked>" : "<dangling>" })';
}
/// A composited layer that can be followed by a [FollowerLayer].
......@@ -861,10 +854,10 @@ class LeaderLayer extends ContainerLayer {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('offset: $offset');
description.add('link: $link');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<Offset>('offset', offset));
description.add(new DiagnosticsProperty<LayerLink>('link', link));
}
}
......@@ -1050,12 +1043,9 @@ class FollowerLayer extends ContainerLayer {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('link: $link');
if (_lastTransform != null) {
description.add('transform:');
description.addAll(debugDescribeTransform(getLastTransform()));
}
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<LayerLink>('link', link));
description.add(new TransformProperty('transform', getLastTransform(), defaultValue: null));
}
}
......@@ -17,7 +17,7 @@ import 'layer.dart';
import 'node.dart';
import 'semantics.dart';
export 'package:flutter/foundation.dart' show FlutterError, InformationCollector;
export 'package:flutter/foundation.dart' show FlutterError, InformationCollector, DiagnosticsNode, DiagnosticsProperty, StringProperty, DoubleProperty, EnumProperty, IntProperty;
export 'package:flutter/gestures.dart' show HitTestEntry, HitTestResult;
export 'package:flutter/painting.dart';
......@@ -1318,7 +1318,7 @@ class PipelineOwner {
/// [RenderObject.markNeedsLayout] so that if a parent has queried the intrinsic
/// or baseline information, it gets marked dirty whenever the child's geometry
/// changes.
abstract class RenderObject extends AbstractNode implements HitTestTarget {
abstract class RenderObject extends AbstractNode with TreeDiagnosticsMixin implements HitTestTarget {
/// Initializes internal fields for subclasses.
RenderObject() {
_needsCompositing = isRepaintBoundary || alwaysNeedsCompositing;
......@@ -2748,25 +2748,13 @@ 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.
@override
String toStringDeep([String prefixLineOne = '', String prefixOtherLines = '']) {
final RenderObject debugPreviousActiveLayout = _debugActiveLayout;
_debugActiveLayout = null;
String result = '$prefixLineOne$this\n';
final String childrenDescription = debugDescribeChildren(prefixOtherLines);
final String descriptionPrefix = childrenDescription != '' ? '$prefixOtherLines \u2502 ' : '$prefixOtherLines ';
final List<String> description = <String>[];
debugFillDescription(description);
result += description
.expand((String description) => debugWordWrap(description, 65, wrapIndent: ' '))
.map<String>((String line) => "$descriptionPrefix$line\n")
.join();
if (childrenDescription == '') {
final String prefix = prefixOtherLines.trimRight();
if (prefix != '')
result += '$prefix\n';
} else {
result += childrenDescription;
}
final String result = super.toStringDeep(prefixLineOne, prefixOtherLines);
_debugActiveLayout = debugPreviousActiveLayout;
return result;
}
......@@ -2776,42 +2764,35 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
///
/// This includes the same information for this RenderObject as given by
/// [toStringDeep], but does not recurse to any children.
@override
String toStringShallow([String joiner = '; ']) {
final RenderObject debugPreviousActiveLayout = _debugActiveLayout;
_debugActiveLayout = null;
final StringBuffer result = new StringBuffer();
result.write('${this}$joiner'); // TODO(ianh): https://github.com/dart-lang/sdk/issues/28206
final List<String> description = <String>[];
debugFillDescription(description);
result.write(description.join(joiner));
final String result = super.toStringShallow(joiner);
_debugActiveLayout = debugPreviousActiveLayout;
return result.toString();
return result;
}
/// Accumulates a list of strings describing the current node's fields, one
/// field per string. Subclasses should override this to have their
/// information included in [toStringDeep].
@protected
void debugFillDescription(List<String> description) {
if (debugCreator != null)
description.add('creator: $debugCreator');
description.add('parentData: $parentData${ _debugCanParentUseSize == true ? " (can use size)" : ""}');
description.add('constraints: $constraints');
if (_layer != null) // don't access it via the "layer" getter since that's only valid when we don't need paint
description.add('layer: $_layer');
if (_semantics != null)
description.add('semantics: $_semantics');
if (isBlockingSemanticsOfPreviouslyPaintedNodes)
description.add('blocks semantics of earlier render objects below the common boundary');
if (isSemanticBoundary)
description.add('semantic boundary');
@override
void debugFillProperties(List<DiagnosticsNode> description) {
description.add(new DiagnosticsProperty<dynamic>('creator', debugCreator, defaultValue: null));
description.add(new DiagnosticsProperty<ParentData>('parentData', parentData, tooltip: _debugCanParentUseSize == true ? "can use size" : null));
description.add(new DiagnosticsProperty<Constraints>('constraints', constraints));
// don't access it via the "layer" getter since that's only valid when we don't need paint
description.add(new DiagnosticsProperty<OffsetLayer>('layer', _layer, defaultValue: null));
description.add(new DiagnosticsProperty<SemanticsNode>('_semantics', _semantics, defaultValue: null));
description.add(new FlagProperty(
'isBlockingSemanticsOfPreviouslyPaintedNodes',
value: isBlockingSemanticsOfPreviouslyPaintedNodes,
ifTrue: 'blocks semantics of earlier render objects below the common boundary',
));
description.add(new FlagProperty('isSemanticBoundary', value: isSemanticBoundary, ifTrue: 'semantic boundary'));
}
/// Returns a string describing the current node's descendants. Each line of
/// the subtree in the output should be indented by the prefix argument.
@protected
String debugDescribeChildren(String prefix) => '';
@override
List<DiagnosticsNode> debugDescribeChildren() => <DiagnosticsNode>[];
/// Attempt to make this or a descendant RenderObject visible on screen.
///
......@@ -2901,10 +2882,8 @@ abstract class RenderObjectWithChildMixin<ChildType extends RenderObject> extend
}
@override
String debugDescribeChildren(String prefix) {
if (child != null)
return '$prefix \u2502\n${child.toStringDeep('$prefix \u2514\u2500child: ', '$prefix ')}';
return '';
List<DiagnosticsNode> debugDescribeChildren() {
return child != null ? <DiagnosticsNode>[child.toDiagnosticsNode(name: 'child')] : <DiagnosticsNode>[];
}
}
......@@ -3204,26 +3183,21 @@ abstract class ContainerRenderObjectMixin<ChildType extends RenderObject, Parent
}
@override
String debugDescribeChildren(String prefix) {
List<DiagnosticsNode> debugDescribeChildren() {
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
if (firstChild != null) {
final StringBuffer result = new StringBuffer()
..write(prefix)
..write(' \u2502\n');
ChildType child = firstChild;
int count = 1;
while (child != lastChild) {
result.write(child.toStringDeep("$prefix \u251C\u2500child $count: ", "$prefix \u2502"));
while (true) {
children.add(child.toDiagnosticsNode(name: 'child $count'));
if (child == lastChild)
break;
count += 1;
final ParentDataType childParentData = child.parentData;
child = childParentData.nextSibling;
}
if (child != null) {
assert(child == lastChild);
result.write(child.toStringDeep("$prefix \u2514\u2500child $count: ", "$prefix "));
}
return result.toString();
}
return '';
return children;
}
}
......
......@@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/services.dart';
import 'box.dart';
import 'debug.dart';
import 'object.dart';
......@@ -369,10 +370,7 @@ class RenderParagraph extends RenderBox {
}
@override
String debugDescribeChildren(String prefix) {
return '$prefix \u2558\u2550\u2566\u2550\u2550 text \u2550\u2550\u2550\n'
'${text.toString("$prefix \u2551 ")}' // TextSpan includes a newline
'$prefix \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n'
'${prefix.trimRight()}\n';
List<DiagnosticsNode> debugDescribeChildren() {
return <DiagnosticsNode>[text.toDiagnosticsNode(name: 'text', style: DiagnosticsTreeStyle.transition)];
}
}
......@@ -177,9 +177,9 @@ class RenderPadding extends RenderShiftedBox {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('padding: $padding');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<EdgeInsets>('padding', padding));
}
}
......@@ -236,9 +236,9 @@ abstract class RenderAligningShiftedBox extends RenderShiftedBox {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('alignment: $alignment');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<FractionalOffset>('alignment', alignment));
}
}
......@@ -366,10 +366,10 @@ class RenderPositionedBox extends RenderAligningShiftedBox {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('widthFactor: ${_widthFactor ?? "expand"}');
description.add('heightFactor: ${_heightFactor ?? "expand"}');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DoubleProperty('widthFactor', _widthFactor, ifNull: 'expand'));
description.add(new DoubleProperty('heightFactor', _heightFactor, ifNull: 'expand'));
}
}
......@@ -479,12 +479,12 @@ class RenderConstrainedOverflowBox extends RenderAligningShiftedBox {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('minWidth: ${minWidth ?? "use parent minWidth constraint"}');
description.add('maxWidth: ${maxWidth ?? "use parent maxWidth constraint"}');
description.add('minHeight: ${minHeight ?? "use parent minHeight constraint"}');
description.add('maxHeight: ${maxHeight ?? "use parent maxHeight constraint"}');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DoubleProperty('minWidth', minWidth, ifNull: 'use parent minWidth constraint'));
description.add(new DoubleProperty('maxWidth', maxWidth, ifNull: 'use parent maxWidth constraint'));
description.add(new DoubleProperty('minHeight', minHeight, ifNull: 'use parent minHeight constraint'));
description.add(new DoubleProperty('maxHeight', maxHeight, ifNull: 'use parent maxHeight constraint'));
}
}
......@@ -689,10 +689,10 @@ class RenderFractionallySizedOverflowBox extends RenderAligningShiftedBox {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('widthFactor: ${_widthFactor ?? "pass-through"}');
description.add('heightFactor: ${_heightFactor ?? "pass-through"}');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DoubleProperty('widthFactor', _widthFactor, ifNull: 'pass-through'));
description.add(new DoubleProperty('heightFactor', _heightFactor, ifNull: 'pass-through'));
}
}
......@@ -945,9 +945,9 @@ class RenderBaseline extends RenderShiftedBox {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('baseline: $baseline');
description.add('baselineType: $baselineType');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DoubleProperty('baseline', baseline));
description.add(new EnumProperty<TextBaseline>('baselineType', baselineType));
}
}
......@@ -467,7 +467,7 @@ class SliverConstraints extends Constraints {
/// A sliver can occupy space in several different ways, which is why this class
/// contains multiple values.
@immutable
class SliverGeometry {
class SliverGeometry implements TreeDiagnostics {
/// Creates an object that describes the amount of space occupied by a sliver.
///
/// If the [layoutExtent] argument is null, [layoutExtent] defaults to the
......@@ -621,37 +621,45 @@ class SliverGeometry {
@override
String toString() {
final StringBuffer buffer = new StringBuffer();
buffer.write('SliverGeometry(');
buffer.write('scrollExtent: ${scrollExtent.toStringAsFixed(1)}, ');
if (paintExtent > 0.0) {
if (visible) {
buffer.write('paintExtent: ${paintExtent.toStringAsFixed(1)}, ');
} else {
buffer.write('paintExtent: ${paintExtent.toStringAsFixed(1)} but not painting, ');
}
} else if (paintExtent == 0.0) {
if (visible) {
buffer.write('paintExtent: ${paintExtent.toStringAsFixed(1)} but visible, ');
return toDiagnosticsNode(style: DiagnosticsTreeStyle.singleLine).toStringDeep();
}
@override
String toStringDeep([String prefix = '', String indentPrefix ]) {
return toDiagnosticsNode().toStringDeep(prefix, indentPrefix);
}
@override
DiagnosticsNode toDiagnosticsNode({
String name,
DiagnosticsTreeStyle style: DiagnosticsTreeStyle.whitespace,
}) {
return new DiagnosticsNode.lazy(
name: name,
object: this,
description: 'SliverGeometry',
style: style,
emptyBodyDescription: '<no decorations specified>',
fillProperties: (List<DiagnosticsNode> properties) {
properties.add(new DoubleProperty('scrollExtent', scrollExtent));
if (paintExtent > 0.0) {
properties.add(new DoubleProperty('paintExtent', paintExtent, unit : visible ? null : ' but not painting'));
} else if (paintExtent == 0.0) {
if (visible) {
properties.add(new DoubleProperty('paintExtent', paintExtent, unit: visible ? null : ' but visible'));
}
properties.add(new FlagProperty('visible', value: visible, ifFalse: 'hidden'));
} else {
buffer.write('hidden, ');
// Negative paintExtent!
properties.add(new DoubleProperty('paintExtent', paintExtent, tooltip: '!'));
}
} else {
buffer.write('paintExtent: ${paintExtent.toStringAsFixed(1)} (!), ');
}
if (paintOrigin != 0.0)
buffer.write('paintOrigin: ${paintOrigin.toStringAsFixed(1)}, ');
if (layoutExtent != paintExtent)
buffer.write('layoutExtent: ${layoutExtent.toStringAsFixed(1)}, ');
buffer.write('maxPaintExtent: ${maxPaintExtent.toStringAsFixed(1)}, ');
if (hitTestExtent != paintExtent)
buffer.write('hitTestExtent: ${hitTestExtent.toStringAsFixed(1)}, ');
if (hasVisualOverflow)
buffer.write('hasVisualOverflow: true, ');
if (scrollOffsetCorrection != null)
buffer.write('scrollOffsetCorrection: ${scrollOffsetCorrection.toStringAsFixed(1)}');
buffer.write(')');
return buffer.toString();
properties.add(new DoubleProperty('paintOrigin', paintOrigin, defaultValue: 0.0));
properties.add(new DoubleProperty('layoutExtent', layoutExtent, defaultValue: paintExtent));
properties.add(new DoubleProperty('maxPaintExtent', maxPaintExtent));
properties.add(new DoubleProperty('hitTestExtent', hitTestExtent, defaultValue: paintExtent));
properties.add(new DiagnosticsProperty<bool>('hasVisualOverflow', hasVisualOverflow, defaultValue: false));
properties.add(new DoubleProperty('scrollOffsetCorrection', scrollOffsetCorrection, defaultValue: null));
});
}
}
......@@ -1321,9 +1329,9 @@ abstract class RenderSliver extends RenderObject {
void handleEvent(PointerEvent event, SliverHitTestEntry entry) { }
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('geometry: $geometry');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<SliverGeometry>('geometry', geometry));
}
}
......
......@@ -517,13 +517,9 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (firstChild != null) {
description.add('currently live children: ${indexOf(firstChild)} to ${indexOf(lastChild)}');
} else {
description.add('no children current live');
}
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsNode.message(firstChild != null ? 'currently live children: ${indexOf(firstChild)} to ${indexOf(lastChild)}' : 'no children current live'));
}
/// Asserts that the reified child list is not empty and has a contiguous
......@@ -546,40 +542,27 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
}
@override
String debugDescribeChildren(String prefix) {
StringBuffer result;
List<DiagnosticsNode> debugDescribeChildren() {
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
if (firstChild != null) {
result = new StringBuffer()
..write(prefix)
..write(' \u2502\n');
RenderBox child = firstChild;
while (child != lastChild) {
while (true) {
final SliverMultiBoxAdaptorParentData childParentData = child.parentData;
result.write(child.toStringDeep("$prefix \u251C\u2500child with index ${childParentData.index}: ", "$prefix \u2502"));
children.add(child.toDiagnosticsNode(name: "child with index ${childParentData.index}"));
if (child == lastChild)
break;
child = childParentData.nextSibling;
}
if (child != null) {
assert(child == lastChild);
final SliverMultiBoxAdaptorParentData childParentData = child.parentData;
if (_keepAliveBucket.isEmpty) {
result.write(child.toStringDeep("$prefix \u2514\u2500child with index ${childParentData.index}: ", "$prefix "));
} else {
result.write(child.toStringDeep("$prefix \u251C\u2500child with index ${childParentData.index}: ", "$prefix \u254E"));
}
}
}
if (_keepAliveBucket.isNotEmpty) {
result ??= new StringBuffer()
..write(prefix)
..write(' \u254E\n');
final List<int> indices = _keepAliveBucket.keys.toList()..sort();
final int lastIndex = indices.removeLast();
if (indices.isNotEmpty) {
for (int index in indices)
result.write(_keepAliveBucket[index].toStringDeep("$prefix \u251C\u2500child with index $index (kept alive offstage): ", "$prefix \u254E"));
for (int index in indices) {
children.add(_keepAliveBucket[index].toDiagnosticsNode(
name: "child with index $index (kept alive offstage)",
style: DiagnosticsTreeStyle.offstage,
));
}
result.write(_keepAliveBucket[lastIndex].toStringDeep("$prefix \u2514\u2500child with index $lastIndex (kept alive offstage): ", "$prefix "));
}
return result?.toString() ?? '';
return children;
}
}
......@@ -204,18 +204,10 @@ abstract class RenderSliverPersistentHeader extends RenderSliver with RenderObje
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
try {
description.add('maxExtent: ${maxExtent.toStringAsFixed(1)}');
} catch (e) {
description.add('maxExtent: EXCEPTION (${e.runtimeType})');
}
try {
description.add('child position: ${childMainAxisPosition(child).toStringAsFixed(1)}');
} catch (e) {
description.add('child position: EXCEPTION (${e.runtimeType})');
}
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DoubleProperty.lazy('maxExtent', () => maxExtent));
description.add(new DoubleProperty.lazy('child position', () => childMainAxisPosition(child)));
}
}
......@@ -465,9 +457,9 @@ abstract class RenderSliverFloatingPersistentHeader extends RenderSliverPersiste
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('effective scroll offset: ${_effectiveScrollOffset?.toStringAsFixed(1)}');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DoubleProperty('effective scroll offset', _effectiveScrollOffset));
}
}
......
......@@ -524,11 +524,11 @@ class RenderStack extends RenderBox
Rect describeApproximatePaintClip(RenderObject child) => _hasVisualOverflow ? Offset.zero & size : null;
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('alignment: $alignment');
description.add('fit: $fit');
description.add('overflow: $overflow');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<FractionalOffset>('alignment', alignment));
description.add(new EnumProperty<StackFit>('fit', fit));
description.add(new EnumProperty<Overflow>('overflow', overflow));
}
}
......@@ -600,8 +600,8 @@ class RenderIndexedStack extends RenderStack {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('index: $index');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new IntProperty('index', index));
}
}
......@@ -1278,46 +1278,34 @@ class RenderTable extends RenderBox {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (border != null)
description.add('border: $border');
if (_columnWidths.isNotEmpty)
description.add('specified column widths: $_columnWidths');
description.add('default column width: $defaultColumnWidth');
description.add('table size: $columns\u00D7$rows');
description.add('column offsets: ${ _columnLefts ?? "unknown" }');
description.add('row offsets: ${ _rowTops ?? "unknown" }');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<TableBorder>('border', border, defaultValue: null));
description.add(new DiagnosticsProperty<Map<int, TableColumnWidth>>('specified column widths', _columnWidths, hidden: _columnWidths.isEmpty));
description.add(new DiagnosticsProperty<TableColumnWidth>('default column width', defaultColumnWidth));
description.add(new MessageProperty('table size', '$columns\u00D7$rows'));
description.add(new IterableProperty<double>('column offsets', _columnLefts, ifNull: 'unknown'));
description.add(new IterableProperty<double>('row offsets', _rowTops, ifNull: "unknown"));
}
@override
String debugDescribeChildren(String prefix) {
final StringBuffer result = new StringBuffer();
result.writeln('$prefix \u2502');
final int lastIndex = _children.length - 1;
if (lastIndex < 0) {
result.writeln('$prefix \u2514\u2500table is empty');
} else {
for (int y = 0; y < rows; y += 1) {
for (int x = 0; x < columns; x += 1) {
final int xy = x + y * columns;
final RenderBox child = _children[xy];
if (child != null) {
if (xy < lastIndex) {
result.write('${child.toStringDeep("$prefix \u251C\u2500child ($x, $y): ", "$prefix \u2502")}');
} else {
result.write('${child.toStringDeep("$prefix \u2514\u2500child ($x, $y): ", "$prefix ")}');
}
} else {
if (xy < lastIndex) {
result.writeln('$prefix \u251C\u2500child ($x, $y) is null');
} else {
result.writeln('$prefix \u2514\u2500child ($x, $y) is null');
}
}
}
List<DiagnosticsNode> debugDescribeChildren() {
if (_children.isEmpty) {
return <DiagnosticsNode>[new DiagnosticsNode.message('table is empty')];
}
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
for (int y = 0; y < rows; y += 1) {
for (int x = 0; x < columns; x += 1) {
final int xy = x + y * columns;
final RenderBox child = _children[xy];
final String name = 'child ($x, $y)';
if (child != null)
children.add(child.toDiagnosticsNode(name: name));
else
children.add(new DiagnosticsProperty<Object>(name, null, ifNull: 'is null', showSeparator: false));
}
}
return result.toString();
return children;
}
}
......@@ -211,16 +211,18 @@ class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox>
}
@override
void debugFillDescription(List<String> description) {
// call to ${super.debugFillDescription(prefix)} is omitted because the root superclasses don't include any interesting information for this class
void debugFillProperties(List<DiagnosticsNode> description) {
// call to ${super.debugFillProperties(description)} is omitted because the
// root superclasses don't include any interesting information for this
// class
assert(() {
description.add('debug mode enabled - ${Platform.operatingSystem}');
description.add(new DiagnosticsNode.message('debug mode enabled - ${Platform.operatingSystem}'));
return true;
});
description.add('window size: ${ui.window.physicalSize} (in physical pixels)');
description.add('device pixel ratio: ${ui.window.devicePixelRatio} (physical pixels per logical pixel)');
description.add('configuration: $configuration (in logical pixels)');
description.add(new DiagnosticsProperty<Size>('window size', ui.window.physicalSize, tooltip: 'in physical pixels'));
description.add(new DoubleProperty('device pixel ratio', ui.window.devicePixelRatio, tooltip: 'physical pixels per logical pixel'));
description.add(new DiagnosticsProperty<ViewConfiguration>('configuration', configuration, tooltip: 'in logical pixels'));
if (ui.window.semanticsEnabled)
description.add('semantics enabled');
description.add(new DiagnosticsNode.message('semantics enabled'));
}
}
......@@ -468,29 +468,28 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
// TODO(ianh): semantics - shouldn't walk the invisible children
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('$axisDirection');
description.add('offset: $offset');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new EnumProperty<AxisDirection>('axisDirection', axisDirection));
description.add(new DiagnosticsProperty<ViewportOffset>('offset', offset));
}
@override
String debugDescribeChildren(String prefix) {
if (firstChild == null)
return '$prefix\n';
int count = indexOfFirstChild;
final StringBuffer result = new StringBuffer()
..write(prefix)
..write(' \u2502\n');
List<DiagnosticsNode> debugDescribeChildren() {
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
RenderSliver child = firstChild;
while (child != lastChild) {
result.write(child.toStringDeep("$prefix \u251C\u2500${labelForChild(count)}: ", "$prefix \u2502"));
if (child == null)
return children;
int count = indexOfFirstChild;
while (true) {
children.add(child.toDiagnosticsNode(name: labelForChild(count)));
if (child == lastChild)
break;
count += 1;
child = childAfter(child);
}
assert(child == lastChild);
result.write(child.toStringDeep("$prefix \u2514\u2500${labelForChild(count)}: ", "$prefix "));
return result.toString();
return children;
}
// API TO BE IMPLEMENTED BY SUBCLASSES
......@@ -1046,9 +1045,9 @@ class RenderViewport extends RenderViewportBase<SliverPhysicalContainerParentDat
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('anchor: $anchor');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DoubleProperty('anchor', anchor));
}
}
......
......@@ -593,13 +593,13 @@ class RenderWrap extends RenderBox with ContainerRenderObjectMixin<RenderBox, Wr
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('direction: $direction');
description.add('alignment: $alignment');
description.add('spacing: $spacing');
description.add('runAlignment: $runAlignment');
description.add('runSpacing: $runSpacing');
description.add('crossAxisAlignment: $runSpacing');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new EnumProperty<Axis>('direction', direction));
description.add(new EnumProperty<WrapAlignment>('alignment', alignment));
description.add(new DoubleProperty('spacing', spacing));
description.add(new EnumProperty<WrapAlignment>('runAlignment', runAlignment));
description.add(new DoubleProperty('runSpacing', runSpacing));
description.add(new DoubleProperty('crossAxisAlignment', runSpacing));
}
}
......@@ -215,11 +215,10 @@ class AnimatedCrossFade extends StatefulWidget {
_AnimatedCrossFadeState createState() => new _AnimatedCrossFadeState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('$crossFadeState');
if (alignment != FractionalOffset.topCenter)
description.add('alignment: $alignment');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new EnumProperty<CrossFadeState>('crossFadeState', crossFadeState));
description.add(new DiagnosticsProperty<FractionalOffset>('alignment', alignment, defaultValue: FractionalOffset.topCenter));
}
}
......@@ -353,11 +352,10 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('${widget.crossFadeState}');
description.add('$_controller');
if (widget.alignment != FractionalOffset.topCenter)
description.add('alignment: ${widget.alignment}');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new EnumProperty<CrossFadeState>('crossFadeState', widget.crossFadeState));
description.add(new DiagnosticsProperty<AnimationController>('controller', _controller, showName: false));
description.add(new DiagnosticsProperty<FractionalOffset>('alignment', widget.alignment, defaultValue: FractionalOffset.topCenter));
}
}
......@@ -198,15 +198,17 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (_keepingAlive)
description.add('keeping subtree alive');
if (_handles == null) {
description.add('no notifications ever received');
} else {
description.add('${_handles.length} active client${ _handles.length == 1 ? "" : "s" }');
}
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new FlagProperty('_keepingAlive', value: _keepingAlive, ifTrue: 'keeping subtree alive'));
description.add(new DiagnosticsProperty<Map<Listenable, VoidCallback>>(
'handles',
_handles,
description: _handles != null ?
'${_handles.length} active client${ _handles.length == 1 ? "" : "s" }' :
null,
ifNull: 'no notifications ever received',
));
}
}
......
......@@ -207,12 +207,12 @@ class Banner extends StatelessWidget {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('"$message"');
description.add('$location');
description.add('$color');
'$textStyle'.split('\n').map((String value) => 'text $value').forEach(description.add);
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new StringProperty('message', message, showName: false));
description.add(new EnumProperty<BannerLocation>('location', location));
description.add(new DiagnosticsProperty<Color>('color', color, showName: false));
textStyle?.debugFillProperties(description, prefix: 'text ');
}
}
......@@ -243,13 +243,13 @@ class CheckedModeBanner extends StatelessWidget {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
String message = 'disabled';
assert(() {
message = '"SLOW MODE"';
return true;
});
description.add(message);
description.add(new DiagnosticsNode.message(message));
}
}
This diff is collapsed.
......@@ -84,8 +84,8 @@ class DecoratedBox extends SingleChildRenderObjectWidget {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
String label;
if (position != null) {
switch (position) {
......@@ -97,10 +97,15 @@ class DecoratedBox extends SingleChildRenderObjectWidget {
break;
}
} else {
description.add('position: NULL');
label = 'decoration';
}
description.add(decoration != null ? '$label: $decoration' : 'no decoration');
description.add(new EnumProperty<DecorationPosition>('position', position, hidden: position != null));
description.add(new DiagnosticsProperty<Decoration>(
label,
decoration,
ifNull: 'no decoration',
showName: decoration != null,
));
}
}
......@@ -355,21 +360,14 @@ class Container extends StatelessWidget {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (alignment != null)
description.add('$alignment');
if (padding != null)
description.add('padding: $padding');
if (decoration != null)
description.add('bg: $decoration');
if (foregroundDecoration != null)
description.add('fg: $foregroundDecoration');
if (constraints != null)
description.add('$constraints');
if (margin != null)
description.add('margin: $margin');
if (transform != null)
description.add('has transform');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<FractionalOffset>('alignment', alignment, showName: false, defaultValue: null));
description.add(new DiagnosticsProperty<EdgeInsets>('padding', padding, defaultValue: null));
description.add(new DiagnosticsProperty<Decoration>('bg', decoration, defaultValue: null));
description.add(new DiagnosticsProperty<Decoration>('fg', foregroundDecoration, defaultValue: null));
description.add(new DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: null));
description.add(new DiagnosticsProperty<EdgeInsets>('margin', margin, defaultValue: null));
description.add(new ObjectFlagProperty<Matrix4>.has('transform', transform));
}
}
......@@ -254,25 +254,18 @@ class EditableText extends StatefulWidget {
EditableTextState createState() => new EditableTextState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('controller: $controller');
description.add('focusNode: $focusNode');
if (obscureText != false)
description.add('obscureText: $obscureText');
if (autocorrect != true)
description.add('autocorrect: $autocorrect');
description.add('${style.toString().split("\n").join(", ")}');
if (textAlign != null)
description.add('$textAlign');
if (textScaleFactor != null)
description.add('textScaleFactor: $textScaleFactor');
if (maxLines != 1)
description.add('maxLines: $maxLines');
if (autofocus != false)
description.add('autofocus: $autofocus');
if (keyboardType != null)
description.add('keyboardType: $keyboardType');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<TextEditingController>('controller', controller));
description.add(new DiagnosticsProperty<FocusNode>('focusNode', focusNode));
description.add(new DiagnosticsProperty<bool>('obscureText', obscureText, defaultValue: false));
description.add(new DiagnosticsProperty<bool>('autocorrect', autocorrect, defaultValue: true));
style?.debugFillProperties(description);
description.add(new EnumProperty<TextAlign>('textAlign', textAlign, defaultValue: null));
description.add(new DoubleProperty('textScaleFactor', textScaleFactor, defaultValue: null));
description.add(new IntProperty('maxLines', maxLines, defaultValue: 1));
description.add(new DiagnosticsProperty<bool>('autofocus', autofocus, defaultValue: false));
description.add(new EnumProperty<TextInputType>('keyboardType', keyboardType, defaultValue: null));
}
}
......
......@@ -354,29 +354,27 @@ class FocusScopeNode extends Object with TreeDiagnosticsMixin {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
if (_focus != null)
description.add('focus: $_focus');
description.add(new DiagnosticsProperty<FocusNode>('focus', _focus));
}
@override
String debugDescribeChildren(String prefix) {
final StringBuffer buffer = new StringBuffer();
List<DiagnosticsNode> debugDescribeChildren() {
final List<DiagnosticsNode> children = <DiagnosticsNode>[];
if (_firstChild != null) {
FocusScopeNode child = _firstChild;
int count = 1;
while (child != _lastChild) {
buffer.write(child.toStringDeep("$prefix \u251C\u2500child $count: ", "$prefix \u2502"));
count += 1;
while (true) {
children.add(child.toDiagnosticsNode(name: "child $count"));
if (child == _lastChild)
break;
child = child._nextSibling;
}
if (child != null) {
assert(child == _lastChild);
buffer.write(child.toStringDeep("$prefix \u2514\u2500child $count: ", "$prefix "));
count += 1;
}
}
return buffer.toString();
return children;
}
}
......
......@@ -613,27 +613,17 @@ class RawGestureDetectorState extends State<RawGestureDetector> {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
if (_recognizers == null) {
description.add('DISPOSED');
description.add(new DiagnosticsNode.message('DISPOSED'));
} else {
final List<String> gestures = _recognizers.values.map<String>((GestureRecognizer recognizer) => recognizer.toStringShort()).toList();
if (gestures.isEmpty)
gestures.add('<none>');
description.add('gestures: ${gestures.join(", ")}');
}
switch (widget.behavior) {
case HitTestBehavior.translucent:
description.add('behavior: translucent');
break;
case HitTestBehavior.opaque:
description.add('behavior: opaque');
break;
case HitTestBehavior.deferToChild:
description.add('behavior: defer-to-child');
break;
description.add(new IterableProperty<String>('gestures', gestures));
}
description.add(new EnumProperty<HitTestBehavior>('behavior', widget.behavior, defaultValue: null));
}
}
......
......@@ -114,16 +114,10 @@ class Icon extends StatelessWidget {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (icon != null) {
description.add('$icon');
} else {
description.add('<empty>');
}
if (size != null)
description.add('size: $size');
if (color != null)
description.add('color: $color');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<IconData>('icon', icon, ifNull: '<empty>', showName: false));
description.add(new DoubleProperty('size', size, defaultValue: null));
description.add(new DiagnosticsProperty<Color>('color', color, defaultValue: null));
}
}
......@@ -71,8 +71,8 @@ class IconTheme extends InheritedWidget {
bool updateShouldNotify(IconTheme old) => data != old.data;
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('$data');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<IconThemeData>('data', data, showName: false));
}
}
......@@ -284,25 +284,17 @@ class Image extends StatefulWidget {
_ImageState createState() => new _ImageState();
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('image: $image');
if (width != null)
description.add('width: $width');
if (height != null)
description.add('height: $height');
if (color != null)
description.add('color: $color');
if (colorBlendMode != null)
description.add('colorBlendMode: $colorBlendMode');
if (fit != null)
description.add('fit: $fit');
if (alignment != null)
description.add('alignment: $alignment');
if (repeat != ImageRepeat.noRepeat)
description.add('repeat: $repeat');
if (centerSlice != null)
description.add('centerSlice: $centerSlice');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<ImageProvider>('image', image));
description.add(new DoubleProperty('width', width, defaultValue: null));
description.add(new DoubleProperty('height', height, defaultValue: null));
description.add(new DiagnosticsProperty<Color>('color', color, defaultValue: null));
description.add(new EnumProperty<BlendMode>('colorBlendMode', colorBlendMode, defaultValue: null));
description.add(new EnumProperty<BoxFit>('fit', fit, defaultValue: null));
description.add(new DiagnosticsProperty<FractionalOffset>('alignment', alignment, defaultValue: null));
description.add(new EnumProperty<ImageRepeat>('repeat', repeat, defaultValue: ImageRepeat.noRepeat));
description.add(new DiagnosticsProperty<Rect>('centerSlice', centerSlice, defaultValue: null));
}
}
......@@ -374,9 +366,9 @@ class _ImageState extends State<Image> {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
description.add('stream: $_imageStream');
description.add('pixels: $_imageInfo');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<ImageStream>('stream', _imageStream));
description.add(new DiagnosticsProperty<ImageInfo>('pixels', _imageInfo));
}
}
......@@ -80,16 +80,10 @@ class ImageIcon extends StatelessWidget {
}
@override
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
if (image != null) {
description.add('$image');
} else {
description.add('<empty>');
}
if (size != null)
description.add('size: $size');
if (color != null)
description.add('color: $color');
void debugFillProperties(List<DiagnosticsNode> description) {
super.debugFillProperties(description);
description.add(new DiagnosticsProperty<ImageProvider>('image', image, ifNull: '<empty>', showName: false));
description.add(new DoubleProperty('size', size, defaultValue: null));
description.add(new DiagnosticsProperty<Color>('color', color, defaultValue: null));
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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