Commit fefdb92e authored by Adam Barth's avatar Adam Barth

Merge pull request #961 from abarth/transform_origin

Add an origin parameter to transforms
parents 58e013c4 ffc6eaa9
......@@ -287,13 +287,13 @@ class RenderShrinkWrapHeight extends RenderProxyBox {
double getMinIntrinsicWidth(BoxConstraints constraints) {
if (child == null)
return constraints.constrainWidth(0.0);
return child.getMinIntrinsicWidth(_getInnerConstraints(constraints));
return child.getMinIntrinsicWidth(_getInnerConstraints(constraints));
}
double getMaxIntrinsicWidth(BoxConstraints constraints) {
if (child == null)
return constraints.constrainWidth(0.0);
return child.getMaxIntrinsicWidth(_getInnerConstraints(constraints));
return child.getMaxIntrinsicWidth(_getInnerConstraints(constraints));
}
double getMinIntrinsicHeight(BoxConstraints constraints) {
......@@ -516,13 +516,24 @@ class RenderDecoratedBox extends RenderProxyBox {
class RenderTransform extends RenderProxyBox {
RenderTransform({
Matrix4 transform,
Offset origin,
RenderBox child
}) : super(child) {
assert(transform != null);
this.transform = transform;
this.origin = origin;
}
Matrix4 _transform;
Offset _origin;
Offset get origin => _origin;
void set origin (Offset newOrigin) {
if (_origin == newOrigin)
return;
_origin = newOrigin;
markNeedsPaint();
}
void set transform(Matrix4 newTransform) {
assert(newTransform != null);
......@@ -562,10 +573,20 @@ class RenderTransform extends RenderProxyBox {
markNeedsPaint();
}
Matrix4 get _effectiveTransform {
if (_origin == null)
return _transform;
return new Matrix4
.identity()
.translate(_origin.dx, _origin.dy)
.multiply(_transform)
.translate(-_origin.dx, -_origin.dy);
}
bool hitTest(HitTestResult result, { Point position }) {
Matrix4 inverse = new Matrix4.zero();
// TODO(abarth): Check the determinant for degeneracy.
inverse.copyInverse(_transform);
inverse.copyInverse(_effectiveTransform);
Vector3 position3 = new Vector3(position.x, position.y, 0.0);
Vector3 transformed3 = inverse.transform3(position3);
......@@ -575,18 +596,18 @@ class RenderTransform extends RenderProxyBox {
void paint(PaintingContext context, Offset offset) {
if (child != null)
context.paintChildWithTransform(child, offset.toPoint(), _transform);
context.paintChildWithTransform(child, offset.toPoint(), _effectiveTransform);
}
void applyPaintTransform(Matrix4 transform) {
super.applyPaintTransform(transform);
transform.multiply(_transform);
transform.multiply(_effectiveTransform);
}
String debugDescribeSettings(String prefix) {
List<String> result = _transform.toString().split('\n').map((s) => '$prefix $s\n').toList();
result.removeLast();
return '${super.debugDescribeSettings(prefix)}${prefix}transform matrix:\n${result.join()}';
return '${super.debugDescribeSettings(prefix)}${prefix}transform matrix:\n${result.join()}\n${prefix}origin: ${origin}\n';
}
}
......
......@@ -154,17 +154,19 @@ class ClipOval extends OneChildRenderObjectWrapper {
// POSITIONING AND SIZING NODES
class Transform extends OneChildRenderObjectWrapper {
Transform({ Key key, this.transform, Widget child })
Transform({ Key key, this.transform, this.origin, Widget child })
: super(key: key, child: child);
final Matrix4 transform;
final Offset origin;
RenderTransform createNode() => new RenderTransform(transform: transform);
RenderTransform createNode() => new RenderTransform(transform: transform, origin: origin);
RenderTransform get renderObject => super.renderObject;
void syncRenderObject(Transform old) {
super.syncRenderObject(old);
renderObject.transform = transform;
renderObject.origin = origin;
}
}
......
import 'package:sky/widgets.dart';
import 'package:test/test.dart';
import 'widget_tester.dart';
void main() {
test('Transform origin', () {
WidgetTester tester = new WidgetTester();
bool didReceiveTap = false;
tester.pumpFrame(() {
return new Stack([
new Positioned(
top: 100.0,
left: 100.0,
child: new Container(
width: 100.0,
height: 100.0,
decoration: new BoxDecoration(
backgroundColor: new Color(0xFF0000FF)
)
)
),
new Positioned(
top: 100.0,
left: 100.0,
child: new Container(
width: 100.0,
height: 100.0,
child: new Transform(
transform: new Matrix4.identity().scale(0.5, 0.5),
origin: new Offset(100.0, 50.0),
child: new GestureDetector(
onTap: () {
didReceiveTap = true;
},
child: new Container()
)
)
)
)
]);
});
expect(didReceiveTap, isFalse);
tester.tapAt(new Point(110.0, 110.0));
expect(didReceiveTap, isFalse);
tester.tapAt(new Point(190.0, 150.0));
expect(didReceiveTap, isTrue);
});
}
......@@ -90,7 +90,10 @@ class WidgetTester {
}
void tap(Widget widget, { int pointer: 1 }) {
Point location = getCenter(widget);
tapAt(getCenter(widget), pointer: pointer);
}
void tapAt(Point location, { int pointer: 1 }) {
HitTestResult result = _hitTest(location);
TestPointer p = new TestPointer(pointer);
_dispatchEvent(p.down(location), result);
......
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