Merge pull request #961 from abarth/transform_origin
Add an origin parameter to transforms
This commit is contained in:
commit
fefdb92e5e
@ -287,13 +287,13 @@ class RenderShrinkWrapHeight extends RenderProxyBox {
|
|||||||
double getMinIntrinsicWidth(BoxConstraints constraints) {
|
double getMinIntrinsicWidth(BoxConstraints constraints) {
|
||||||
if (child == null)
|
if (child == null)
|
||||||
return constraints.constrainWidth(0.0);
|
return constraints.constrainWidth(0.0);
|
||||||
return child.getMinIntrinsicWidth(_getInnerConstraints(constraints));
|
return child.getMinIntrinsicWidth(_getInnerConstraints(constraints));
|
||||||
}
|
}
|
||||||
|
|
||||||
double getMaxIntrinsicWidth(BoxConstraints constraints) {
|
double getMaxIntrinsicWidth(BoxConstraints constraints) {
|
||||||
if (child == null)
|
if (child == null)
|
||||||
return constraints.constrainWidth(0.0);
|
return constraints.constrainWidth(0.0);
|
||||||
return child.getMaxIntrinsicWidth(_getInnerConstraints(constraints));
|
return child.getMaxIntrinsicWidth(_getInnerConstraints(constraints));
|
||||||
}
|
}
|
||||||
|
|
||||||
double getMinIntrinsicHeight(BoxConstraints constraints) {
|
double getMinIntrinsicHeight(BoxConstraints constraints) {
|
||||||
@ -516,13 +516,24 @@ class RenderDecoratedBox extends RenderProxyBox {
|
|||||||
class RenderTransform extends RenderProxyBox {
|
class RenderTransform extends RenderProxyBox {
|
||||||
RenderTransform({
|
RenderTransform({
|
||||||
Matrix4 transform,
|
Matrix4 transform,
|
||||||
|
Offset origin,
|
||||||
RenderBox child
|
RenderBox child
|
||||||
}) : super(child) {
|
}) : super(child) {
|
||||||
assert(transform != null);
|
assert(transform != null);
|
||||||
this.transform = transform;
|
this.transform = transform;
|
||||||
|
this.origin = origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix4 _transform;
|
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) {
|
void set transform(Matrix4 newTransform) {
|
||||||
assert(newTransform != null);
|
assert(newTransform != null);
|
||||||
@ -562,10 +573,20 @@ class RenderTransform extends RenderProxyBox {
|
|||||||
markNeedsPaint();
|
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 }) {
|
bool hitTest(HitTestResult result, { Point position }) {
|
||||||
Matrix4 inverse = new Matrix4.zero();
|
Matrix4 inverse = new Matrix4.zero();
|
||||||
// TODO(abarth): Check the determinant for degeneracy.
|
// TODO(abarth): Check the determinant for degeneracy.
|
||||||
inverse.copyInverse(_transform);
|
inverse.copyInverse(_effectiveTransform);
|
||||||
|
|
||||||
Vector3 position3 = new Vector3(position.x, position.y, 0.0);
|
Vector3 position3 = new Vector3(position.x, position.y, 0.0);
|
||||||
Vector3 transformed3 = inverse.transform3(position3);
|
Vector3 transformed3 = inverse.transform3(position3);
|
||||||
@ -575,18 +596,18 @@ class RenderTransform extends RenderProxyBox {
|
|||||||
|
|
||||||
void paint(PaintingContext context, Offset offset) {
|
void paint(PaintingContext context, Offset offset) {
|
||||||
if (child != null)
|
if (child != null)
|
||||||
context.paintChildWithTransform(child, offset.toPoint(), _transform);
|
context.paintChildWithTransform(child, offset.toPoint(), _effectiveTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyPaintTransform(Matrix4 transform) {
|
void applyPaintTransform(Matrix4 transform) {
|
||||||
super.applyPaintTransform(transform);
|
super.applyPaintTransform(transform);
|
||||||
transform.multiply(_transform);
|
transform.multiply(_effectiveTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
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
|
// POSITIONING AND SIZING NODES
|
||||||
|
|
||||||
class Transform extends OneChildRenderObjectWrapper {
|
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);
|
: super(key: key, child: child);
|
||||||
|
|
||||||
final Matrix4 transform;
|
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;
|
RenderTransform get renderObject => super.renderObject;
|
||||||
|
|
||||||
void syncRenderObject(Transform old) {
|
void syncRenderObject(Transform old) {
|
||||||
super.syncRenderObject(old);
|
super.syncRenderObject(old);
|
||||||
renderObject.transform = transform;
|
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 }) {
|
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);
|
HitTestResult result = _hitTest(location);
|
||||||
TestPointer p = new TestPointer(pointer);
|
TestPointer p = new TestPointer(pointer);
|
||||||
_dispatchEvent(p.down(location), result);
|
_dispatchEvent(p.down(location), result);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user