Merge pull request #961 from abarth/transform_origin
Add an origin parameter to transforms
This commit is contained in:
commit
fefdb92e5e
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
51
packages/unit/test/widget/transform_test.dart
Normal file
51
packages/unit/test/widget/transform_test.dart
Normal file
@ -0,0 +1,51 @@
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user