Merge pull request #1657 from Hixie/debugging
Reduce latency of low-volume debugPrint output
diff --git a/sky/engine/core/painting/Offset.dart b/sky/engine/core/painting/Offset.dart
index 744e532..88771ef 100644
--- a/sky/engine/core/painting/Offset.dart
+++ b/sky/engine/core/painting/Offset.dart
@@ -61,5 +61,5 @@
/// Compares two Offsets for equality.
bool operator ==(dynamic other) => other is Offset && super == other;
- String toString() => "Offset($dx, $dy)";
+ String toString() => "Offset(${dx.toStringAsFixed(1)}, ${dy.toStringAsFixed(1)})";
}
diff --git a/sky/engine/core/painting/Point.dart b/sky/engine/core/painting/Point.dart
index 3ba60c1..68e6b37 100644
--- a/sky/engine/core/painting/Point.dart
+++ b/sky/engine/core/painting/Point.dart
@@ -36,5 +36,5 @@
return result;
}
- String toString() => "Point($x, $y)";
+ String toString() => "Point(${x.toStringAsFixed(1)}, ${y.toStringAsFixed(1)})";
}
diff --git a/sky/engine/core/painting/Rect.dart b/sky/engine/core/painting/Rect.dart
index 0a45764..42d1329 100644
--- a/sky/engine/core/painting/Rect.dart
+++ b/sky/engine/core/painting/Rect.dart
@@ -142,5 +142,5 @@
int get hashCode => _value.fold(373, (value, item) => (37 * value + item.hashCode));
- String toString() => "Rect.fromLTRB($left, $top, $right, $bottom)";
+ String toString() => "Rect.fromLTRB(${left.toStringAsFixed(1)}, ${top.toStringAsFixed(1)}, ${right.toStringAsFixed(1)}, ${bottom.toStringAsFixed(1)})";
}
diff --git a/sky/engine/core/painting/Size.dart b/sky/engine/core/painting/Size.dart
index 94a0d15..7af64da 100644
--- a/sky/engine/core/painting/Size.dart
+++ b/sky/engine/core/painting/Size.dart
@@ -61,5 +61,5 @@
/// Compares two Sizes for equality.
bool operator ==(dynamic other) => other is Size && super == other;
- String toString() => "Size($width, $height)";
+ String toString() => "Size(${width.toStringAsFixed(1)}, ${height.toStringAsFixed(1)})";
}
diff --git a/sky/packages/sky/lib/src/material/icon.dart b/sky/packages/sky/lib/src/material/icon.dart
index 8c25d35..46b46ab 100644
--- a/sky/packages/sky/lib/src/material/icon.dart
+++ b/sky/packages/sky/lib/src/material/icon.dart
@@ -23,6 +23,8 @@
}
int get hashCode => color.hashCode;
+
+ String toString() => '$color';
}
class IconTheme extends InheritedWidget {
@@ -45,6 +47,10 @@
bool updateShouldNotify(IconTheme old) => data != old.data;
+ void debugFillDescription(List<String> description) {
+ super.debugFillDescription(description);
+ description.add('$data');
+ }
}
AssetBundle _initIconBundle() {
@@ -63,7 +69,10 @@
this.type: '',
this.color,
this.colorFilter
- }) : super(key: key);
+ }) : super(key: key) {
+ assert(size != null);
+ assert(type != null);
+ }
final int size;
final String type;
@@ -108,4 +117,10 @@
colorFilter: colorFilter
);
}
+
+ void debugFillDescription(List<String> description) {
+ super.debugFillDescription(description);
+ description.add('$type');
+ description.add('size: $size');
+ }
}
diff --git a/sky/packages/sky/lib/src/material/icon_button.dart b/sky/packages/sky/lib/src/material/icon_button.dart
index f629806..4ea19a3 100644
--- a/sky/packages/sky/lib/src/material/icon_button.dart
+++ b/sky/packages/sky/lib/src/material/icon_button.dart
@@ -36,4 +36,9 @@
)
);
}
+
+ void debugFillDescription(List<String> description) {
+ super.debugFillDescription(description);
+ description.add('$icon');
+ }
}
diff --git a/sky/packages/sky/lib/src/material/material_button.dart b/sky/packages/sky/lib/src/material/material_button.dart
index bf5380d..1eb4591 100644
--- a/sky/packages/sky/lib/src/material/material_button.dart
+++ b/sky/packages/sky/lib/src/material/material_button.dart
@@ -47,6 +47,12 @@
final bool enabled;
final ButtonColor textColor;
final GestureTapCallback onPressed;
+
+ void debugFillDescription(List<String> description) {
+ super.debugFillDescription(description);
+ if (!enabled)
+ description.add('disabled');
+ }
}
abstract class MaterialButtonState<T extends MaterialButton> extends State<T> {
diff --git a/sky/packages/sky/lib/src/material/progress_indicator.dart b/sky/packages/sky/lib/src/material/progress_indicator.dart
index 73052ec..e688a44 100644
--- a/sky/packages/sky/lib/src/material/progress_indicator.dart
+++ b/sky/packages/sky/lib/src/material/progress_indicator.dart
@@ -14,15 +14,15 @@
const double _kMinCircularProgressIndicatorSize = 15.0;
const double _kCircularProgressIndicatorStrokeWidth = 3.0;
+// TODO(hansmuller) implement the support for buffer indicator
+
abstract class ProgressIndicator extends StatefulComponent {
ProgressIndicator({
Key key,
- this.value,
- this.bufferValue
+ this.value
}) : super(key: key);
final double value; // Null for non-determinate progress indicator.
- final double bufferValue; // TODO(hansmuller) implement the support for this.
Color _getBackgroundColor(BuildContext context) => Theme.of(context).primarySwatch[200];
Color _getValueColor(BuildContext context) => Theme.of(context).primaryColor;
@@ -31,6 +31,11 @@
Widget _buildIndicator(BuildContext context, double performanceValue);
_ProgressIndicatorState createState() => new _ProgressIndicatorState();
+
+ void debugFillDescription(List<String> description) {
+ super.debugFillDescription(description);
+ description.add('${(value.clamp(0.0, 1.0) * 100.0).toStringAsFixed(1)}%');
+ }
}
class _ProgressIndicatorState extends State<ProgressIndicator> {
@@ -72,9 +77,8 @@
class LinearProgressIndicator extends ProgressIndicator {
LinearProgressIndicator({
Key key,
- double value,
- double bufferValue
- }) : super(key: key, value: value, bufferValue: bufferValue);
+ double value
+ }) : super(key: key, value: value);
void _paint(BuildContext context, double performanceValue, Canvas canvas, Size size) {
Paint paint = new Paint()
@@ -120,9 +124,8 @@
CircularProgressIndicator({
Key key,
- double value,
- double bufferValue
- }) : super(key: key, value: value, bufferValue: bufferValue);
+ double value
+ }) : super(key: key, value: value);
void _paint(BuildContext context, double performanceValue, Canvas canvas, Size size) {
Paint paint = new Paint()
diff --git a/sky/packages/sky/lib/src/material/tabs.dart b/sky/packages/sky/lib/src/material/tabs.dart
index 00025c8..3a9d40e 100644
--- a/sky/packages/sky/lib/src/material/tabs.dart
+++ b/sky/packages/sky/lib/src/material/tabs.dart
@@ -281,6 +281,16 @@
final String text;
final String icon;
+
+ String toString() {
+ if (text != null && icon != null)
+ return '"$text" ($icon)';
+ if (text != null)
+ return '"$text"';
+ if (icon != null)
+ return '$icon';
+ return 'EMPTY TAB LABEL';
+ }
}
class Tab extends StatelessComponent {
@@ -345,6 +355,11 @@
child: centeredLabel
);
}
+
+ void debugFillDescription(List<String> description) {
+ super.debugFillDescription(description);
+ description.add('$label');
+ }
}
class _TabsScrollBehavior extends BoundedBehavior {
diff --git a/sky/packages/sky/lib/src/material/theme.dart b/sky/packages/sky/lib/src/material/theme.dart
index aeff56f..7d9233a 100644
--- a/sky/packages/sky/lib/src/material/theme.dart
+++ b/sky/packages/sky/lib/src/material/theme.dart
@@ -28,4 +28,9 @@
}
bool updateShouldNotify(Theme old) => data != old.data;
+
+ void debugFillDescription(List<String> description) {
+ super.debugFillDescription(description);
+ description.add('$data');
+ }
}
diff --git a/sky/packages/sky/lib/src/material/theme_data.dart b/sky/packages/sky/lib/src/material/theme_data.dart
index 7566fd4..3b789d0 100644
--- a/sky/packages/sky/lib/src/material/theme_data.dart
+++ b/sky/packages/sky/lib/src/material/theme_data.dart
@@ -124,4 +124,6 @@
value = 37 * value + accentColorBrightness.hashCode;
return value;
}
+
+ String toString() => '$primaryColor $brightness etc...';
}
diff --git a/sky/packages/sky/lib/src/material/title.dart b/sky/packages/sky/lib/src/material/title.dart
index deca5d1..293320c 100644
--- a/sky/packages/sky/lib/src/material/title.dart
+++ b/sky/packages/sky/lib/src/material/title.dart
@@ -17,4 +17,9 @@
updateTaskDescription(title, Theme.of(context).primaryColor);
return child;
}
+
+ void debugFillDescription(List<String> description) {
+ super.debugFillDescription(description);
+ description.add('"$title"');
+ }
}
diff --git a/sky/packages/sky/lib/src/rendering/box.dart b/sky/packages/sky/lib/src/rendering/box.dart
index b26a99a..2341e81 100644
--- a/sky/packages/sky/lib/src/rendering/box.dart
+++ b/sky/packages/sky/lib/src/rendering/box.dart
@@ -254,7 +254,21 @@
return value;
}
- String toString() => "BoxConstraints($minWidth<=w<=$maxWidth, $minHeight<=h<=$maxHeight)";
+ String toString() {
+ if (minWidth == double.INFINITY && minHeight == double.INFINITY)
+ return 'BoxConstraints(biggest)';
+ if (minWidth == 0 && maxWidth == double.INFINITY &&
+ minHeight == 0 && maxHeight == double.INFINITY)
+ return 'BoxConstraints(unconstrained)';
+ String describe(double min, double max, String dim) {
+ if (min == max)
+ return '$dim=${min.toStringAsFixed(1)}';
+ return '${min.toStringAsFixed(1)}<=$dim<=${max.toStringAsFixed(1)}';
+ }
+ final String width = describe(minWidth, maxWidth, 'w');
+ final String height = describe(minHeight, maxHeight, 'h');
+ return 'BoxConstraints($width, $height)';
+ }
}
/// A hit test entry used by [RenderBox]
diff --git a/sky/packages/sky/lib/src/rendering/stack.dart b/sky/packages/sky/lib/src/rendering/stack.dart
index c6ba3f6..54b329b 100644
--- a/sky/packages/sky/lib/src/rendering/stack.dart
+++ b/sky/packages/sky/lib/src/rendering/stack.dart
@@ -42,8 +42,8 @@
return new RelativeRect.fromLTRB(
rect.left - container.left,
rect.top - container.top,
- container.right - rect.left + rect.width,
- container.bottom - rect.top + rect.height
+ container.right - rect.right,
+ container.bottom - rect.bottom
);
}
@@ -132,7 +132,7 @@
return value;
}
- String toString() => "RelativeRect.fromLTRB($left, $top, $right, $bottom)";
+ String toString() => "RelativeRect.fromLTRB(${left.toStringAsFixed(1)}, ${top.toStringAsFixed(1)}, ${right.toStringAsFixed(1)}, ${bottom.toStringAsFixed(1)})";
}
/// Parent data for use with [RenderStack]
diff --git a/sky/packages/sky/lib/src/rendering/view.dart b/sky/packages/sky/lib/src/rendering/view.dart
index 7b0d354..a9b739b 100644
--- a/sky/packages/sky/lib/src/rendering/view.dart
+++ b/sky/packages/sky/lib/src/rendering/view.dart
@@ -23,6 +23,8 @@
/// The orientation of the output surface (aspirational)
final int orientation;
+
+ String toString() => '$size';
}
/// The root of the render tree
@@ -53,7 +55,7 @@
ViewConstraints get rootConstraints => _rootConstraints;
ViewConstraints _rootConstraints;
void set rootConstraints(ViewConstraints value) {
- if (_rootConstraints == value)
+ if (rootConstraints == value)
return;
_rootConstraints = value;
markNeedsLayout();
@@ -80,12 +82,12 @@
}
void performLayout() {
- if (_rootConstraints.orientation != _orientation) {
+ if (rootConstraints.orientation != _orientation) {
if (_orientation != null && child != null)
- child.rotate(oldAngle: _orientation, newAngle: _rootConstraints.orientation, time: timeForRotation);
- _orientation = _rootConstraints.orientation;
+ child.rotate(oldAngle: _orientation, newAngle: rootConstraints.orientation, time: timeForRotation);
+ _orientation = rootConstraints.orientation;
}
- _size = _rootConstraints.size;
+ _size = rootConstraints.size;
assert(!_size.isInfinite);
if (child != null)
@@ -127,4 +129,7 @@
}
Rect get paintBounds => Point.origin & size;
+
+ String debugDescribeSettings(String prefix) => '${prefix}view width: ${ui.view.width} (in device pixels)\n${prefix}view height: ${ui.view.height} (in device pixels)\n${prefix}device pixel ratio: ${ui.view.devicePixelRatio} (device pixels per logical pixel)\n${prefix}root constraints: $rootConstraints (in logical pixels)\n';
+ // call to ${super.debugDescribeSettings(prefix)} is omitted because the root superclasses don't include any interesting information for this class
}
diff --git a/sky/packages/sky/lib/src/widgets/animated_container.dart b/sky/packages/sky/lib/src/widgets/animated_container.dart
index 307fdd4..8017dba 100644
--- a/sky/packages/sky/lib/src/widgets/animated_container.dart
+++ b/sky/packages/sky/lib/src/widgets/animated_container.dart
@@ -124,7 +124,6 @@
void _updateAllVariables() {
setState(() {
_updateVariable(_constraints);
- _updateVariable(_constraints);
_updateVariable(_decoration);
_updateVariable(_foregroundDecoration);
_updateVariable(_margin);
@@ -224,4 +223,24 @@
height: _height?.value
);
}
+
+ void debugFillDescription(List<String> description) {
+ super.debugFillDescription(description);
+ if (_constraints != null)
+ description.add('has constraints');
+ if (_decoration != null)
+ description.add('has background');
+ if (_foregroundDecoration != null)
+ description.add('has foreground');
+ if (_margin != null)
+ description.add('has margin');
+ if (_padding != null)
+ description.add('has padding');
+ if (_transform != null)
+ description.add('has transform');
+ if (_width != null)
+ description.add('has width');
+ if (_height != null)
+ description.add('has height');
+ }
}
diff --git a/sky/packages/sky/lib/src/widgets/basic.dart b/sky/packages/sky/lib/src/widgets/basic.dart
index 776e33b..ac64a03 100644
--- a/sky/packages/sky/lib/src/widgets/basic.dart
+++ b/sky/packages/sky/lib/src/widgets/basic.dart
@@ -314,7 +314,7 @@
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
- description.add('constraints: $constraints');
+ description.add('$constraints');
}
}
@@ -549,6 +549,26 @@
return current;
}
+ void debugFillDescription(List<String> description) {
+ super.debugFillDescription(description);
+ if (constraints != null)
+ description.add('$constraints');
+ if (decoration != null)
+ description.add('has background');
+ if (foregroundDecoration != null)
+ description.add('has foreground');
+ if (margin != null)
+ description.add('margin: $margin');
+ if (padding != null)
+ description.add('padding: $padding');
+ if (transform != null)
+ description.add('has transform');
+ if (width != null)
+ description.add('width: $width');
+ if (height != null)
+ description.add('height: $height');
+ }
+
}
@@ -672,8 +692,11 @@
needsLayout = true;
}
- if (needsLayout)
- renderObject.markNeedsLayout();
+ if (needsLayout) {
+ AbstractNode targetParent = renderObject.parent;
+ if (targetParent is RenderObject)
+ targetParent.markNeedsLayout();
+ }
}
void debugFillDescription(List<String> description) {
@@ -768,7 +791,9 @@
final FlexParentData parentData = renderObject.parentData;
if (parentData.flex != flex) {
parentData.flex = flex;
- renderObject.markNeedsLayout();
+ AbstractNode targetParent = renderObject.parent;
+ if (targetParent is RenderObject)
+ targetParent.markNeedsLayout();
}
}
diff --git a/sky/packages/sky/lib/src/widgets/focus.dart b/sky/packages/sky/lib/src/widgets/focus.dart
index 5f2f129..c5592b0 100644
--- a/sky/packages/sky/lib/src/widgets/focus.dart
+++ b/sky/packages/sky/lib/src/widgets/focus.dart
@@ -22,8 +22,8 @@
Widget child
}) : super(key: key, child: child);
- final bool scopeFocused;
final FocusState focusState;
+ final bool scopeFocused;
// These are mutable because we implicitly change them when they're null in
// certain cases, basically pretending retroactively that we were constructed
@@ -61,6 +61,15 @@
return false;
}
+ void debugFillDescription(List<String> description) {
+ super.debugFillDescription(description);
+ if (scopeFocused)
+ description.add('this scope has focus');
+ if (focusedScope != null)
+ description.add('focused subscope: $focusedScope');
+ if (focusedWidget != null)
+ description.add('focused widget: $focusedWidget');
+ }
}
class Focus extends StatefulComponent {
diff --git a/sky/packages/sky/lib/src/widgets/transitions.dart b/sky/packages/sky/lib/src/widgets/transitions.dart
index bd2f7da..c696131 100644
--- a/sky/packages/sky/lib/src/widgets/transitions.dart
+++ b/sky/packages/sky/lib/src/widgets/transitions.dart
@@ -4,11 +4,13 @@
import 'package:flutter/animation.dart';
import 'package:vector_math/vector_math_64.dart' show Matrix4;
+import 'package:flutter/rendering.dart';
import 'basic.dart';
import 'framework.dart';
export 'package:flutter/animation.dart' show AnimationDirection;
+export 'package:flutter/rendering.dart' show RelativeRect;
abstract class TransitionComponent extends StatefulComponent {
TransitionComponent({
@@ -150,6 +152,47 @@
}
}
+/// An animated variable containing a RelativeRectangle
+///
+/// This class specializes the interpolation of AnimatedValue<RelativeRect> to
+/// be appropriate for rectangles that are described in terms of offsets from
+/// other rectangles.
+class AnimatedRelativeRectValue extends AnimatedValue<RelativeRect> {
+ AnimatedRelativeRectValue(RelativeRect begin, { RelativeRect end, Curve curve, Curve reverseCurve })
+ : super(begin, end: end, curve: curve, reverseCurve: reverseCurve);
+
+ RelativeRect lerp(double t) => RelativeRect.lerp(begin, end, t);
+}
+
+/// Animated version of [Positioned].
+/// Only works if it's the child of a [Stack].
+class PositionedTransition extends TransitionWithChild {
+ PositionedTransition({
+ Key key,
+ this.rect,
+ PerformanceView performance,
+ Widget child
+ }) : super(key: key,
+ performance: performance,
+ child: child) {
+ assert(rect != null);
+ }
+
+ final AnimatedRelativeRectValue rect;
+
+ Widget buildWithChild(BuildContext context, Widget child) {
+ performance.updateVariable(rect);
+ return new Positioned(
+ top: rect.value.top,
+ right: rect.value.right,
+ bottom: rect.value.bottom,
+ left: rect.value.left,
+ child: child
+ );
+ }
+}
+
+
typedef Widget BuilderFunction(BuildContext context);
class BuilderTransition extends TransitionComponent {
diff --git a/sky/unit/test/widget/positioned_test.dart b/sky/unit/test/widget/positioned_test.dart
new file mode 100644
index 0000000..7adecc8
--- /dev/null
+++ b/sky/unit/test/widget/positioned_test.dart
@@ -0,0 +1,74 @@
+import 'package:flutter/animation.dart';
+import 'package:flutter/rendering.dart';
+import 'package:flutter/widgets.dart';
+import 'package:test/test.dart';
+
+import 'widget_tester.dart';
+
+void main() {
+
+ test('Can animate position data', () {
+ testWidgets((WidgetTester tester) {
+
+ final AnimatedRelativeRectValue rect = new AnimatedRelativeRectValue(
+ new RelativeRect.fromRect(
+ new Rect.fromLTRB(10.0, 20.0, 20.0, 30.0),
+ new Rect.fromLTRB(0.0, 10.0, 100.0, 110.0)
+ ),
+ end: new RelativeRect.fromRect(
+ new Rect.fromLTRB(80.0, 90.0, 90.0, 100.0),
+ new Rect.fromLTRB(0.0, 10.0, 100.0, 110.0)
+ ),
+ curve: linear
+ );
+ final Performance performance = new Performance(
+ duration: const Duration(seconds: 10)
+ );
+ final List<Size> sizes = <Size>[];
+ final List<Point> positions = <Point>[];
+ final GlobalKey key = new GlobalKey();
+
+ void recordMetrics() {
+ RenderBox box = key.currentContext.findRenderObject();
+ BoxParentData boxParentData = box.parentData;
+ sizes.add(box.size);
+ positions.add(boxParentData.position);
+ }
+
+ tester.pumpWidget(
+ new Center(
+ child: new Container(
+ height: 100.0,
+ width: 100.0,
+ child: new Stack(<Widget>[
+ new PositionedTransition(
+ rect: rect,
+ performance: performance,
+ child: new Container(
+ key: key
+ )
+ )
+ ])
+ )
+ )
+ ); // t=0
+ recordMetrics();
+ performance.play();
+ tester.pump(); // t=0 again
+ recordMetrics();
+ tester.pump(const Duration(seconds: 1)); // t=1
+ recordMetrics();
+ tester.pump(const Duration(seconds: 1)); // t=2
+ recordMetrics();
+ tester.pump(const Duration(seconds: 3)); // t=5
+ recordMetrics();
+ tester.pump(const Duration(seconds: 5)); // t=10
+ recordMetrics();
+
+ expect(sizes, equals([const Size(10.0, 10.0), const Size(10.0, 10.0), const Size(10.0, 10.0), const Size(10.0, 10.0), const Size(10.0, 10.0), const Size(10.0, 10.0)]));
+ expect(positions, equals([const Point(10.0, 10.0), const Point(10.0, 10.0), const Point(17.0, 17.0), const Point(24.0, 24.0), const Point(45.0, 45.0), const Point(80.0, 80.0)]));
+
+ });
+ });
+
+}