From b5ee723305428e3d1809dceb362a3cd85dbe90eb Mon Sep 17 00:00:00 2001 From: Hans Muller Date: Fri, 7 Aug 2015 13:28:19 -0700 Subject: [PATCH] Widget coordinate transforms: localToGlobal(), globalToLocal() --- sky/packages/sky/lib/rendering/block.dart | 6 +++ sky/packages/sky/lib/rendering/box.dart | 47 ++++++++++++++++++++- sky/packages/sky/lib/rendering/object.dart | 3 ++ sky/packages/sky/lib/widgets/framework.dart | 15 +++++++ 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/sky/packages/sky/lib/rendering/block.dart b/sky/packages/sky/lib/rendering/block.dart index 29a70d2f6e8..1fe9b4e2fda 100644 --- a/sky/packages/sky/lib/rendering/block.dart +++ b/sky/packages/sky/lib/rendering/block.dart @@ -6,6 +6,7 @@ import 'dart:math' as math; import 'package:sky/rendering/box.dart'; import 'package:sky/rendering/object.dart'; +import 'package:vector_math/vector_math.dart'; class BlockParentData extends BoxParentData with ContainerParentDataMixin { } @@ -248,6 +249,11 @@ class RenderBlockViewport extends RenderBlockBase { canvas.restore(); } + void applyPaintTransform(Matrix4 transform) { + super.applyPaintTransform(transform); + transform.translate(0.0, startOffset); + } + void hitTestChildren(HitTestResult result, { Point position }) { defaultHitTestChildren(result, position: position + new Offset(0.0, -startOffset)); } diff --git a/sky/packages/sky/lib/rendering/box.dart b/sky/packages/sky/lib/rendering/box.dart index e67c4d83f6c..74bc4a937ba 100644 --- a/sky/packages/sky/lib/rendering/box.dart +++ b/sky/packages/sky/lib/rendering/box.dart @@ -450,6 +450,42 @@ abstract class RenderBox extends RenderObject { _size = inDebugBuild ? new _DebugSize(value, this, debugCanParentUseSize) : value; } + void applyPaintTransform(Matrix4 transform) { + if (parentData is BoxParentData) { + Point position = (parentData as BoxParentData).position; + transform.translate(position.x, position.y); + } + } + + static Point _transformPoint(Matrix4 transform, Point point) { + Vector3 position3 = new Vector3(point.x, point.y, 0.0); + Vector3 transformed3 = transform.transform3(position3); + return new Point(transformed3.x, transformed3.y); + } + + Point globalToLocal(Point point) { + assert(attached); + Matrix4 transform = new Matrix4.identity(); + RenderObject renderer = this; + while(renderer != null) { + renderer.applyPaintTransform(transform); + renderer = renderer.parent; + } + /* double det = */ transform.invert(); + // TODO(abarth): Check the determinant for degeneracy. + return _transformPoint(transform, point); + } + + Point localToGlobal(Point point) { + List renderers = []; + for (RenderObject renderer = this; renderer != null; renderer = renderer.parent) + renderers.add(renderer); + Matrix4 transform = new Matrix4.identity(); + for (RenderObject renderer in renderers.reversed) + renderer.applyPaintTransform(transform); + return _transformPoint(transform, point); + } + Rect get paintBounds => Point.origin & size; void debugPaint(PaintingCanvas canvas, Offset offset) { if (debugPaintSizeEnabled) @@ -550,7 +586,6 @@ class RenderProxyBox extends RenderBox with RenderObjectWithChildMixin result = _transform.toString().split('\n').map((s) => '$prefix $s\n').toList(); result.removeLast(); diff --git a/sky/packages/sky/lib/rendering/object.dart b/sky/packages/sky/lib/rendering/object.dart index 18ece8d4d70..845bd74576a 100644 --- a/sky/packages/sky/lib/rendering/object.dart +++ b/sky/packages/sky/lib/rendering/object.dart @@ -10,6 +10,7 @@ import 'package:sky/base/debug.dart'; import 'package:sky/base/hit_test.dart'; import 'package:sky/base/node.dart'; import 'package:sky/base/scheduler.dart' as scheduler; +import 'package:vector_math/vector_math.dart'; export 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path; export 'package:sky/base/hit_test.dart' show EventDisposition, HitTestTarget, HitTestEntry, HitTestResult; @@ -412,6 +413,8 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { void debugPaint(PaintingCanvas canvas, Offset offset) { } void paint(PaintingCanvas canvas, Offset offset) { } + void applyPaintTransform(Matrix4 transform) { } + // EVENTS diff --git a/sky/packages/sky/lib/widgets/framework.dart b/sky/packages/sky/lib/widgets/framework.dart index 76b6813ece8..c3f16430477 100644 --- a/sky/packages/sky/lib/widgets/framework.dart +++ b/sky/packages/sky/lib/widgets/framework.dart @@ -369,6 +369,21 @@ abstract class Widget { return '$runtimeType($key; hashCode=$hashCode)'; } + // This function can be safely called when the layout is valid. + // For example Listener or SizeObserver callbacks can safely call + // globalToLocal(). + Point globalToLocal(Point point) { + assert(mounted); + assert(root is RenderBox); + return (root as RenderBox).globalToLocal(point); + } + + // See globalToLocal(). + Point localToGlobal(Point point) { + assert(mounted); + assert(root is RenderBox); + return (root as RenderBox).localToGlobal(point); + } }