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;
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<RenderBox> { }
......@@ -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));
}
......
......@@ -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 <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;
void debugPaint(PaintingCanvas canvas, Offset offset) {
if (debugPaintSizeEnabled)
......@@ -550,7 +586,6 @@ class RenderProxyBox extends RenderBox with RenderObjectWithChildMixin<RenderBox
if (child != null)
canvas.paintChild(child, offset.toPoint());
}
}
class RenderConstrainedBox extends RenderProxyBox {
......@@ -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 }) {
if (child != null) {
assert(child.parentData is BoxParentData);
......@@ -1512,6 +1552,11 @@ class RenderTransform extends RenderProxyBox {
canvas.restore();
}
void applyPaintTransform(Matrix4 transform) {
super.applyPaintTransform(transform);
transform.multiply(_transform);
}
String debugDescribeSettings(String prefix) {
List<String> result = _transform.toString().split('\n').map((s) => '$prefix $s\n').toList();
result.removeLast();
......
......@@ -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
......
......@@ -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);
}
}
......
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