Commit 585f3f62 authored by Hans Muller's avatar Hans Muller

Widget coordinate transforms: localToGlobal(), globalToLocal()

parent 27f5fc4f
...@@ -6,6 +6,7 @@ import 'dart:math' as math; ...@@ -6,6 +6,7 @@ import 'dart:math' as math;
import 'package:sky/rendering/box.dart'; import 'package:sky/rendering/box.dart';
import 'package:sky/rendering/object.dart'; import 'package:sky/rendering/object.dart';
import 'package:vector_math/vector_math.dart';
class BlockParentData extends BoxParentData with ContainerParentDataMixin<RenderBox> { } class BlockParentData extends BoxParentData with ContainerParentDataMixin<RenderBox> { }
...@@ -248,6 +249,11 @@ class RenderBlockViewport extends RenderBlockBase { ...@@ -248,6 +249,11 @@ class RenderBlockViewport extends RenderBlockBase {
canvas.restore(); canvas.restore();
} }
void applyPaintTransform(Matrix4 transform) {
super.applyPaintTransform(transform);
transform.translate(0.0, startOffset);
}
void hitTestChildren(HitTestResult result, { Point position }) { void hitTestChildren(HitTestResult result, { Point position }) {
defaultHitTestChildren(result, position: position + new Offset(0.0, -startOffset)); defaultHitTestChildren(result, position: position + new Offset(0.0, -startOffset));
} }
......
...@@ -450,6 +450,42 @@ abstract class RenderBox extends RenderObject { ...@@ -450,6 +450,42 @@ abstract class RenderBox extends RenderObject {
_size = inDebugBuild ? new _DebugSize(value, this, debugCanParentUseSize) : value; _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 <RenderObject> renderers = <RenderObject>[];
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; Rect get paintBounds => Point.origin & size;
void debugPaint(PaintingCanvas canvas, Offset offset) { void debugPaint(PaintingCanvas canvas, Offset offset) {
if (debugPaintSizeEnabled) if (debugPaintSizeEnabled)
...@@ -550,7 +586,6 @@ class RenderProxyBox extends RenderBox with RenderObjectWithChildMixin<RenderBox ...@@ -550,7 +586,6 @@ class RenderProxyBox extends RenderBox with RenderObjectWithChildMixin<RenderBox
if (child != null) if (child != null)
canvas.paintChild(child, offset.toPoint()); canvas.paintChild(child, offset.toPoint());
} }
} }
class RenderConstrainedBox extends RenderProxyBox { class RenderConstrainedBox extends RenderProxyBox {
...@@ -1261,6 +1296,11 @@ class RenderViewport extends RenderBox with RenderObjectWithChildMixin<RenderBox ...@@ -1261,6 +1296,11 @@ class RenderViewport extends RenderBox with RenderObjectWithChildMixin<RenderBox
} }
} }
void applyPaintTransform(Matrix4 transform) {
super.applyPaintTransform(transform);
transform.translate(-scrollOffset.dx, -scrollOffset.dy);
}
void hitTestChildren(HitTestResult result, { Point position }) { void hitTestChildren(HitTestResult result, { Point position }) {
if (child != null) { if (child != null) {
assert(child.parentData is BoxParentData); assert(child.parentData is BoxParentData);
...@@ -1512,6 +1552,11 @@ class RenderTransform extends RenderProxyBox { ...@@ -1512,6 +1552,11 @@ class RenderTransform extends RenderProxyBox {
canvas.restore(); canvas.restore();
} }
void applyPaintTransform(Matrix4 transform) {
super.applyPaintTransform(transform);
transform.multiply(_transform);
}
String debugDescribeSettings(String prefix) { String debugDescribeSettings(String prefix) {
List<String> result = _transform.toString().split('\n').map((s) => '$prefix $s\n').toList(); List<String> result = _transform.toString().split('\n').map((s) => '$prefix $s\n').toList();
result.removeLast(); result.removeLast();
......
...@@ -10,6 +10,7 @@ import 'package:sky/base/debug.dart'; ...@@ -10,6 +10,7 @@ import 'package:sky/base/debug.dart';
import 'package:sky/base/hit_test.dart'; import 'package:sky/base/hit_test.dart';
import 'package:sky/base/node.dart'; import 'package:sky/base/node.dart';
import 'package:sky/base/scheduler.dart' as scheduler; 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 'dart:sky' show Point, Offset, Size, Rect, Color, Paint, Path;
export 'package:sky/base/hit_test.dart' show EventDisposition, HitTestTarget, HitTestEntry, HitTestResult; export 'package:sky/base/hit_test.dart' show EventDisposition, HitTestTarget, HitTestEntry, HitTestResult;
...@@ -412,6 +413,8 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -412,6 +413,8 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
void debugPaint(PaintingCanvas canvas, Offset offset) { } void debugPaint(PaintingCanvas canvas, Offset offset) { }
void paint(PaintingCanvas canvas, Offset offset) { } void paint(PaintingCanvas canvas, Offset offset) { }
void applyPaintTransform(Matrix4 transform) { }
// EVENTS // EVENTS
......
...@@ -369,6 +369,21 @@ abstract class Widget { ...@@ -369,6 +369,21 @@ abstract class Widget {
return '$runtimeType($key; hashCode=$hashCode)'; 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);
}
} }
......
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