Commit e0107b05 authored by Ian Hickson's avatar Ian Hickson

Merge pull request #756 from Hixie/PointerInputEvent.kind

PointerInput refactor
parents bc1b47e9 f1625556
...@@ -84,8 +84,8 @@ class MineDiggerState extends State<MineDigger> { ...@@ -84,8 +84,8 @@ class MineDiggerState extends State<MineDigger> {
} }
} }
PointerEventListener _pointerDownHandlerFor(int posX, int posY) { PointerDownEventListener _pointerDownHandlerFor(int posX, int posY) {
return (PointerInputEvent event) { return (PointerDownEvent event) {
if (event.buttons == 1) { if (event.buttons == 1) {
probe(posX, posY); probe(posX, posY);
} else if (event.buttons == 2) { } else if (event.buttons == 2) {
...@@ -190,7 +190,7 @@ class MineDiggerState extends State<MineDigger> { ...@@ -190,7 +190,7 @@ class MineDiggerState extends State<MineDigger> {
); );
} }
void handleToolbarPointerDown(PointerInputEvent event) { void handleToolbarPointerDown(PointerDownEvent event) {
setState(() { setState(() {
resetGame(); resetGame();
}); });
......
...@@ -518,10 +518,11 @@ class RenderSolidColor extends RenderDecoratedSector { ...@@ -518,10 +518,11 @@ class RenderSolidColor extends RenderDecoratedSector {
deltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta); deltaTheta = constraints.constrainDeltaTheta(desiredDeltaTheta);
} }
void handleEvent(InputEvent event, HitTestEntry entry) { void handleEvent(PointerEvent event, HitTestEntry entry) {
if (event.type == 'pointerdown') if (event is PointerDownEvent) {
decoration = new BoxDecoration(backgroundColor: const Color(0xFFFF0000)); decoration = new BoxDecoration(backgroundColor: const Color(0xFFFF0000));
else if (event.type == 'pointerup') } else if (event is PointerUpEvent) {
decoration = new BoxDecoration(backgroundColor: backgroundColor); decoration = new BoxDecoration(backgroundColor: backgroundColor);
}
} }
} }
...@@ -41,10 +41,11 @@ class RenderSolidColorBox extends RenderDecoratedBox { ...@@ -41,10 +41,11 @@ class RenderSolidColorBox extends RenderDecoratedBox {
size = constraints.constrain(desiredSize); size = constraints.constrain(desiredSize);
} }
void handleEvent(InputEvent event, BoxHitTestEntry entry) { void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
if (event.type == 'pointerdown') if (event is PointerDownEvent) {
decoration = new BoxDecoration(backgroundColor: const Color(0xFFFF0000)); decoration = new BoxDecoration(backgroundColor: const Color(0xFFFF0000));
else if (event.type == 'pointerup') } else if (event is PointerUpEvent) {
decoration = new BoxDecoration(backgroundColor: backgroundColor); decoration = new BoxDecoration(backgroundColor: backgroundColor);
}
} }
} }
...@@ -23,8 +23,8 @@ class Dot { ...@@ -23,8 +23,8 @@ class Dot {
Dot({ Color color }) : _paint = new Paint()..color = color; Dot({ Color color }) : _paint = new Paint()..color = color;
void update(PointerInputEvent event) { void update(PointerEvent event) {
position = new Point(event.x, event.y); position = event.position;
radius = 5 + (95 * event.pressure); radius = 5 + (95 * event.pressure);
} }
...@@ -36,25 +36,20 @@ class Dot { ...@@ -36,25 +36,20 @@ class Dot {
class RenderTouchDemo extends RenderBox { class RenderTouchDemo extends RenderBox {
final Map<int, Dot> dots = <int, Dot>{}; final Map<int, Dot> dots = <int, Dot>{};
void handleEvent(InputEvent event, BoxHitTestEntry entry) { void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
if (event is PointerInputEvent) { if (event is PointerDownEvent) {
switch (event.type) { Color color = kColors[event.pointer.remainder(kColors.length)];
case 'pointerdown': dots[event.pointer] = new Dot(color: color)..update(event);
Color color = kColors[event.pointer.remainder(kColors.length)]; } else if (event is PointerUpEvent) {
dots[event.pointer] = new Dot(color: color)..update(event); dots.remove(event.pointer);
break; } else if (event is PointerCancelEvent) {
case 'pointerup': dots.clear();
dots.remove(event.pointer); } else if (event is PointerMoveEvent) {
break; dots[event.pointer].update(event);
case 'pointercancel': } else {
dots.clear(); return;
break;
case 'pointermove':
dots[event.pointer].update(event);
break;
}
markNeedsPaint();
} }
markNeedsPaint();
} }
void performLayout() { void performLayout() {
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'dart:ui' as ui; import 'dart:ui' as ui;
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -121,9 +122,9 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> { ...@@ -121,9 +122,9 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> {
}); });
} }
void handlePointerDown(GlobalKey target, PointerInputEvent event) { void handlePointerDown(GlobalKey target, PointerDownEvent event) {
setState(() { setState(() {
markers[MarkerType.touch] = new Point(event.x, event.y); markers[MarkerType.touch] = event.position;
final RenderBox box = target.currentContext.findRenderObject(); final RenderBox box = target.currentContext.findRenderObject();
markers[MarkerType.topLeft] = box.localToGlobal(new Point(0.0, 0.0)); markers[MarkerType.topLeft] = box.localToGlobal(new Point(0.0, 0.0));
final Size size = box.size; final Size size = box.size;
...@@ -139,7 +140,7 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> { ...@@ -139,7 +140,7 @@ class OverlayGeometryAppState extends State<OverlayGeometryApp> {
CardModel cardModel = cardModels[index]; CardModel cardModel = cardModels[index];
return new Listener( return new Listener(
key: cardModel.key, key: cardModel.key,
onPointerDown: (PointerInputEvent e) { return handlePointerDown(cardModel.targetKey, e); }, onPointerDown: (PointerDownEvent event) { return handlePointerDown(cardModel.targetKey, event); },
child: new Card( child: new Card(
key: cardModel.targetKey, key: cardModel.targetKey,
color: cardModel.color, color: cardModel.color,
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:ui' as ui;
import 'arena.dart'; import 'arena.dart';
import 'recognizer.dart'; import 'recognizer.dart';
import 'constants.dart'; import 'constants.dart';
...@@ -16,21 +14,22 @@ enum DragState { ...@@ -16,21 +14,22 @@ enum DragState {
accepted accepted
} }
typedef void GestureDragStartCallback(ui.Point globalPosition); typedef void GestureDragStartCallback(Point globalPosition);
typedef void GestureDragUpdateCallback(double delta); typedef void GestureDragUpdateCallback(double delta);
typedef void GestureDragEndCallback(ui.Offset velocity); typedef void GestureDragEndCallback(Offset velocity);
typedef void GesturePanStartCallback(ui.Point globalPosition); typedef void GesturePanStartCallback(Point globalPosition);
typedef void GesturePanUpdateCallback(ui.Offset delta); typedef void GesturePanUpdateCallback(Offset delta);
typedef void GesturePanEndCallback(ui.Offset velocity); typedef void GesturePanEndCallback(Offset velocity);
typedef void _GesturePolymorphicUpdateCallback<T>(T delta); typedef void _GesturePolymorphicUpdateCallback<T>(T delta);
bool _isFlingGesture(GestureVelocity velocity) { bool _isFlingGesture(Offset velocity) {
double velocitySquared = velocity.x * velocity.x + velocity.y * velocity.y; if (velocity == null)
return velocity.isValid && return false;
velocitySquared > kMinFlingVelocity * kMinFlingVelocity && double velocitySquared = velocity.dx * velocity.dx + velocity.dy * velocity.dy;
velocitySquared < kMaxFlingVelocity * kMaxFlingVelocity; return velocitySquared > kMinFlingVelocity * kMinFlingVelocity
&& velocitySquared < kMaxFlingVelocity * kMaxFlingVelocity;
} }
abstract class _DragGestureRecognizer<T extends dynamic> extends OneSequenceGestureRecognizer { abstract class _DragGestureRecognizer<T extends dynamic> extends OneSequenceGestureRecognizer {
...@@ -42,16 +41,16 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends OneSequenceGest ...@@ -42,16 +41,16 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends OneSequenceGest
GestureDragEndCallback onEnd; GestureDragEndCallback onEnd;
DragState _state = DragState.ready; DragState _state = DragState.ready;
ui.Point _initialPosition; Point _initialPosition;
T _pendingDragDelta; T _pendingDragDelta;
T get _initialPendingDragDelta; T get _initialPendingDragDelta;
T _getDragDelta(PointerInputEvent event); T _getDragDelta(PointerEvent event);
bool get _hasSufficientPendingDragDeltaToAccept; bool get _hasSufficientPendingDragDeltaToAccept;
Map<int, VelocityTracker> _velocityTrackers = new Map<int, VelocityTracker>(); Map<int, VelocityTracker> _velocityTrackers = new Map<int, VelocityTracker>();
void addPointer(PointerInputEvent event) { void addPointer(PointerEvent event) {
startTrackingPointer(event.pointer); startTrackingPointer(event.pointer);
_velocityTrackers[event.pointer] = new VelocityTracker(); _velocityTrackers[event.pointer] = new VelocityTracker();
if (_state == DragState.ready) { if (_state == DragState.ready) {
...@@ -61,12 +60,12 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends OneSequenceGest ...@@ -61,12 +60,12 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends OneSequenceGest
} }
} }
void handleEvent(PointerInputEvent event) { void handleEvent(PointerEvent event) {
assert(_state != DragState.ready); assert(_state != DragState.ready);
if (event.type == 'pointermove') { if (event is PointerMoveEvent) {
VelocityTracker tracker = _velocityTrackers[event.pointer]; VelocityTracker tracker = _velocityTrackers[event.pointer];
assert(tracker != null); assert(tracker != null);
tracker.addPosition(event.timeStamp, event.x, event.y); tracker.addPosition(event.timeStamp, event.position);
T delta = _getDragDelta(event); T delta = _getDragDelta(event);
if (_state == DragState.accepted) { if (_state == DragState.accepted) {
if (onUpdate != null) if (onUpdate != null)
...@@ -104,11 +103,10 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends OneSequenceGest ...@@ -104,11 +103,10 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends OneSequenceGest
VelocityTracker tracker = _velocityTrackers[pointer]; VelocityTracker tracker = _velocityTrackers[pointer];
assert(tracker != null); assert(tracker != null);
GestureVelocity gestureVelocity = tracker.getVelocity(); Offset velocity = tracker.getVelocity();
ui.Offset velocity = ui.Offset.zero; if (velocity != null && _isFlingGesture(velocity))
if (_isFlingGesture(gestureVelocity)) onEnd(velocity);
velocity = new ui.Offset(gestureVelocity.x, gestureVelocity.y); onEnd(Offset.zero);
onEnd(velocity);
} }
_velocityTrackers.clear(); _velocityTrackers.clear();
} }
...@@ -128,7 +126,7 @@ class VerticalDragGestureRecognizer extends _DragGestureRecognizer<double> { ...@@ -128,7 +126,7 @@ class VerticalDragGestureRecognizer extends _DragGestureRecognizer<double> {
}) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd); }) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd);
double get _initialPendingDragDelta => 0.0; double get _initialPendingDragDelta => 0.0;
double _getDragDelta(PointerInputEvent event) => event.dy; double _getDragDelta(PointerEvent event) => event.delta.dy;
bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop; bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop;
} }
...@@ -141,11 +139,11 @@ class HorizontalDragGestureRecognizer extends _DragGestureRecognizer<double> { ...@@ -141,11 +139,11 @@ class HorizontalDragGestureRecognizer extends _DragGestureRecognizer<double> {
}) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd); }) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd);
double get _initialPendingDragDelta => 0.0; double get _initialPendingDragDelta => 0.0;
double _getDragDelta(PointerInputEvent event) => event.dx; double _getDragDelta(PointerEvent event) => event.delta.dx;
bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop; bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop;
} }
class PanGestureRecognizer extends _DragGestureRecognizer<ui.Offset> { class PanGestureRecognizer extends _DragGestureRecognizer<Offset> {
PanGestureRecognizer({ PanGestureRecognizer({
PointerRouter router, PointerRouter router,
GesturePanStartCallback onStart, GesturePanStartCallback onStart,
...@@ -153,8 +151,8 @@ class PanGestureRecognizer extends _DragGestureRecognizer<ui.Offset> { ...@@ -153,8 +151,8 @@ class PanGestureRecognizer extends _DragGestureRecognizer<ui.Offset> {
GesturePanEndCallback onEnd GesturePanEndCallback onEnd
}) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd); }) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd);
ui.Offset get _initialPendingDragDelta => ui.Offset.zero; Offset get _initialPendingDragDelta => Offset.zero;
ui.Offset _getDragDelta(PointerInputEvent event) => new ui.Offset(event.dx, event.dy); Offset _getDragDelta(PointerEvent event) => event.delta;
bool get _hasSufficientPendingDragDeltaToAccept { bool get _hasSufficientPendingDragDeltaToAccept {
return _pendingDragDelta.distance > kPanSlop; return _pendingDragDelta.distance > kPanSlop;
} }
......
...@@ -18,11 +18,12 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer { ...@@ -18,11 +18,12 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
void didExceedDeadline() { void didExceedDeadline() {
resolve(GestureDisposition.accepted); resolve(GestureDisposition.accepted);
onLongPress(); if (onLongPress != null)
onLongPress();
} }
void handlePrimaryPointer(PointerInputEvent event) { void handlePrimaryPointer(PointerEvent event) {
if (event.type == 'pointerup') if (event is PointerUpEvent)
resolve(GestureDisposition.rejected); resolve(GestureDisposition.rejected);
} }
} }
...@@ -15,16 +15,22 @@ class _Vector { ...@@ -15,16 +15,22 @@ class _Vector {
_Vector.fromVOL(List<double> values, int offset, int length) _Vector.fromVOL(List<double> values, int offset, int length)
: _offset = offset, _length = length, _elements = values; : _offset = offset, _length = length, _elements = values;
final int _offset;
int get length => _length; int get length => _length;
final int _length;
final List<double> _elements;
operator [](int i) => _elements[i + _offset]; double operator [](int i) => _elements[i + _offset];
operator []=(int i, double value) => _elements[i + _offset] = value; void operator []=(int i, double value) {
_elements[i + _offset] = value;
}
operator *(_Vector a) { double operator *(_Vector a) {
double result = 0.0; double result = 0.0;
for (int i = 0; i < _length; i++) { for (int i = 0; i < _length; i += 1)
result += this[i] * a[i]; result += this[i] * a[i];
}
return result; return result;
} }
...@@ -39,10 +45,6 @@ class _Vector { ...@@ -39,10 +45,6 @@ class _Vector {
} }
return result; return result;
} }
final int _offset;
final int _length;
final List<double> _elements;
} }
class _Matrix { class _Matrix {
...@@ -51,6 +53,10 @@ class _Matrix { ...@@ -51,6 +53,10 @@ class _Matrix {
_columns = cols, _columns = cols,
_elements = new Float64List(rows * cols); _elements = new Float64List(rows * cols);
final int _rows;
final int _columns;
final List<double> _elements;
double get(int row, int col) => _elements[row * _columns + col]; double get(int row, int col) => _elements[row * _columns + col];
void set(int row, int col, double value) { void set(int row, int col, double value) {
_elements[row * _columns + col] = value; _elements[row * _columns + col] = value;
...@@ -75,10 +81,6 @@ class _Matrix { ...@@ -75,10 +81,6 @@ class _Matrix {
} }
return result; return result;
} }
final int _rows;
final int _columns;
final List<double> _elements;
} }
class PolynomialFit { class PolynomialFit {
...@@ -110,11 +112,10 @@ class LeastSquaresSolver { ...@@ -110,11 +112,10 @@ class LeastSquaresSolver {
// Expand the X vector to a matrix A, pre-multiplied by the weights. // Expand the X vector to a matrix A, pre-multiplied by the weights.
_Matrix a = new _Matrix(n, m); _Matrix a = new _Matrix(n, m);
for (int h = 0; h < m; h++) { for (int h = 0; h < m; h += 1) {
a.set(0, h, w[h]); a.set(0, h, w[h]);
for (int i = 1; i < n; i++) { for (int i = 1; i < n; i += 1)
a.set(i, h, a.get(i - 1, h) * x[h]); a.set(i, h, a.get(i - 1, h) * x[h]);
}
} }
// Apply the Gram-Schmidt process to A to obtain its QR decomposition. // Apply the Gram-Schmidt process to A to obtain its QR decomposition.
...@@ -123,15 +124,13 @@ class LeastSquaresSolver { ...@@ -123,15 +124,13 @@ class LeastSquaresSolver {
_Matrix q = new _Matrix(n, m); _Matrix q = new _Matrix(n, m);
// Upper triangular matrix, row-major order. // Upper triangular matrix, row-major order.
_Matrix r = new _Matrix(n, n); _Matrix r = new _Matrix(n, n);
for (int j = 0; j < n; j++) { for (int j = 0; j < n; j += 1) {
for (int h = 0; h < m; h++) { for (int h = 0; h < m; h += 1)
q.set(j, h, a.get(j, h)); q.set(j, h, a.get(j, h));
} for (int i = 0; i < j; i += 1) {
for (int i = 0; i < j; i++) {
double dot = q.getRow(j) * q.getRow(i); double dot = q.getRow(j) * q.getRow(i);
for (int h = 0; h < m; h++) { for (int h = 0; h < m; h += 1)
q.set(j, h, q.get(j, h) - dot * q.get(i, h)); q.set(j, h, q.get(j, h) - dot * q.get(i, h));
}
} }
double norm = q.getRow(j).norm(); double norm = q.getRow(j).norm();
...@@ -141,56 +140,50 @@ class LeastSquaresSolver { ...@@ -141,56 +140,50 @@ class LeastSquaresSolver {
} }
double inverseNorm = 1.0 / norm; double inverseNorm = 1.0 / norm;
for (int h = 0; h < m; h++) { for (int h = 0; h < m; h += 1)
q.set(j, h, q.get(j, h) * inverseNorm); q.set(j, h, q.get(j, h) * inverseNorm);
} for (int i = 0; i < n; i += 1)
for (int i = 0; i < n; i++) {
r.set(j, i, i < j ? 0.0 : q.getRow(j) * a.getRow(i)); r.set(j, i, i < j ? 0.0 : q.getRow(j) * a.getRow(i));
}
} }
// Solve R B = Qt W Y to find B. This is easy because R is upper triangular. // Solve R B = Qt W Y to find B. This is easy because R is upper triangular.
// We just work from bottom-right to top-left calculating B's coefficients. // We just work from bottom-right to top-left calculating B's coefficients.
_Vector wy = new _Vector(m); _Vector wy = new _Vector(m);
for (int h = 0; h < m; h++) { for (int h = 0; h < m; h += 1)
wy[h] = y[h] * w[h]; wy[h] = y[h] * w[h];
} for (int i = n - 1; i >= 0; i -= 1) {
for (int i = n; i-- != 0;) {
result.coefficients[i] = q.getRow(i) * wy; result.coefficients[i] = q.getRow(i) * wy;
for (int j = n - 1; j > i; j--) { for (int j = n - 1; j > i; j -= 1)
result.coefficients[i] -= r.get(i, j) * result.coefficients[j]; result.coefficients[i] -= r.get(i, j) * result.coefficients[j];
}
result.coefficients[i] /= r.get(i, i); result.coefficients[i] /= r.get(i, i);
} }
// Calculate the coefficient of determination (confidence) as: // Calculate the coefficient of determination (confidence) as:
// 1 - (sumSquaredError / sumSquaredTotal) // 1 - (sumSquaredError / sumSquaredTotal)
// where sumSquaredError is the residual sum of squares (variance of the // ...where sumSquaredError is the residual sum of squares (variance of the
// error), and sumSquaredTotal is the total sum of squares (variance of the // error), and sumSquaredTotal is the total sum of squares (variance of the
// data) where each has been weighted. // data) where each has been weighted.
double yMean = 0.0; double yMean = 0.0;
for (int h = 0; h < m; h++) { for (int h = 0; h < m; h += 1)
yMean += y[h]; yMean += y[h];
}
yMean /= m; yMean /= m;
double sumSquaredError = 0.0; double sumSquaredError = 0.0;
double sumSquaredTotal = 0.0; double sumSquaredTotal = 0.0;
for (int h = 0; h < m; h++) { for (int h = 0; h < m; h += 1) {
double err = y[h] - result.coefficients[0];
double term = 1.0; double term = 1.0;
for (int i = 1; i < n; i++) { double err = y[h] - result.coefficients[0];
for (int i = 1; i < n; i += 1) {
term *= x[h]; term *= x[h];
err -= term * result.coefficients[i]; err -= term * result.coefficients[i];
} }
sumSquaredError += w[h] * w[h] * err * err; sumSquaredError += w[h] * w[h] * err * err;
double v = y[h] - yMean; final double v = y[h] - yMean;
sumSquaredTotal += w[h] * w[h] * v * v; sumSquaredTotal += w[h] * w[h] * v * v;
} }
result.confidence = sumSquaredTotal > 0.000001 ? result.confidence = sumSquaredTotal <= 0.000001 ? 1.0 :
1.0 - (sumSquaredError / sumSquaredTotal) : 1.0 - (sumSquaredError / sumSquaredTotal);
1.0;
return result; return result;
} }
......
...@@ -22,11 +22,9 @@ typedef void GestureMultiTapCancelCallback(int pointer); ...@@ -22,11 +22,9 @@ typedef void GestureMultiTapCancelCallback(int pointer);
/// larger gesture. /// larger gesture.
class _TapTracker { class _TapTracker {
_TapTracker({ PointerInputEvent event, this.entry }) _TapTracker({ PointerDownEvent event, this.entry })
: pointer = event.pointer, : pointer = event.pointer,
_initialPosition = event.position { _initialPosition = event.position;
assert(event.type == 'pointerdown');
}
final int pointer; final int pointer;
final GestureArenaEntry entry; final GestureArenaEntry entry;
...@@ -48,7 +46,7 @@ class _TapTracker { ...@@ -48,7 +46,7 @@ class _TapTracker {
} }
} }
bool isWithinTolerance(PointerInputEvent event, double tolerance) { bool isWithinTolerance(PointerEvent event, double tolerance) {
Offset offset = event.position - _initialPosition; Offset offset = event.position - _initialPosition;
return offset.distance <= tolerance; return offset.distance <= tolerance;
} }
...@@ -92,7 +90,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { ...@@ -92,7 +90,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
_TapTracker _firstTap; _TapTracker _firstTap;
final Map<int, _TapTracker> _trackers = new Map<int, _TapTracker>(); final Map<int, _TapTracker> _trackers = new Map<int, _TapTracker>();
void addPointer(PointerInputEvent event) { void addPointer(PointerEvent event) {
// Ignore out-of-bounds second taps // Ignore out-of-bounds second taps
if (_firstTap != null && if (_firstTap != null &&
!_firstTap.isWithinTolerance(event, kDoubleTapSlop)) !_firstTap.isWithinTolerance(event, kDoubleTapSlop))
...@@ -106,23 +104,19 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { ...@@ -106,23 +104,19 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
tracker.startTrackingPointer(_router, handleEvent); tracker.startTrackingPointer(_router, handleEvent);
} }
void handleEvent(PointerInputEvent event) { void handleEvent(PointerEvent event) {
_TapTracker tracker = _trackers[event.pointer]; _TapTracker tracker = _trackers[event.pointer];
assert(tracker != null); assert(tracker != null);
switch (event.type) { if (event is PointerUpEvent) {
case 'pointerup': if (_firstTap == null)
if (_firstTap == null) _registerFirstTap(tracker);
_registerFirstTap(tracker); else
else _registerSecondTap(tracker);
_registerSecondTap(tracker); } else if (event is PointerMoveEvent) {
break; if (!tracker.isWithinTolerance(event, kDoubleTapTouchSlop))
case 'pointermove':
if (!tracker.isWithinTolerance(event, kDoubleTapTouchSlop))
_reject(tracker);
break;
case 'pointercancel':
_reject(tracker); _reject(tracker);
break; } else if (event is PointerCancelEvent) {
_reject(tracker);
} }
} }
...@@ -228,7 +222,7 @@ class _TapGesture extends _TapTracker { ...@@ -228,7 +222,7 @@ class _TapGesture extends _TapTracker {
_TapGesture({ _TapGesture({
MultiTapGestureRecognizer gestureRecognizer, MultiTapGestureRecognizer gestureRecognizer,
PointerInputEvent event, PointerEvent event,
Duration longTapDelay Duration longTapDelay
}) : gestureRecognizer = gestureRecognizer, }) : gestureRecognizer = gestureRecognizer,
_lastPosition = event.position, _lastPosition = event.position,
...@@ -250,16 +244,16 @@ class _TapGesture extends _TapTracker { ...@@ -250,16 +244,16 @@ class _TapGesture extends _TapTracker {
Point _lastPosition; Point _lastPosition;
Point _finalPosition; Point _finalPosition;
void handleEvent(PointerInputEvent event) { void handleEvent(PointerEvent event) {
assert(event.pointer == pointer); assert(event.pointer == pointer);
if (event.type == 'pointermove') { if (event is PointerMoveEvent) {
if (!isWithinTolerance(event, kTouchSlop)) if (!isWithinTolerance(event, kTouchSlop))
cancel(); cancel();
else else
_lastPosition = event.position; _lastPosition = event.position;
} else if (event.type == 'pointercancel') { } else if (event is PointerCancelEvent) {
cancel(); cancel();
} else if (event.type == 'pointerup') { } else if (event is PointerUpEvent) {
stopTrackingPointer(gestureRecognizer.router, handleEvent); stopTrackingPointer(gestureRecognizer.router, handleEvent);
_finalPosition = event.position; _finalPosition = event.position;
_check(); _check();
...@@ -326,7 +320,7 @@ class MultiTapGestureRecognizer extends GestureRecognizer { ...@@ -326,7 +320,7 @@ class MultiTapGestureRecognizer extends GestureRecognizer {
final Map<int, _TapGesture> _gestureMap = new Map<int, _TapGesture>(); final Map<int, _TapGesture> _gestureMap = new Map<int, _TapGesture>();
void addPointer(PointerInputEvent event) { void addPointer(PointerEvent event) {
assert(!_gestureMap.containsKey(event.pointer)); assert(!_gestureMap.containsKey(event.pointer));
_gestureMap[event.pointer] = new _TapGesture( _gestureMap[event.pointer] = new _TapGesture(
gestureRecognizer: this, gestureRecognizer: this,
......
...@@ -4,16 +4,16 @@ ...@@ -4,16 +4,16 @@
import 'events.dart'; import 'events.dart';
/// A callback that receives a [PointerInputEvent] /// A callback that receives a [PointerEvent]
typedef void PointerRoute(PointerInputEvent event); typedef void PointerRoute(PointerEvent event);
/// A routing table for [PointerInputEvent] events. /// A routing table for [PointerEvent] events.
class PointerRouter { class PointerRouter {
final Map<int, List<PointerRoute>> _routeMap = new Map<int, List<PointerRoute>>(); final Map<int, List<PointerRoute>> _routeMap = new Map<int, List<PointerRoute>>();
/// Adds a route to the routing table /// Adds a route to the routing table.
/// ///
/// Whenever this object routes a [PointerInputEvent] corresponding to /// Whenever this object routes a [PointerEvent] corresponding to
/// pointer, call route. /// pointer, call route.
void addRoute(int pointer, PointerRoute route) { void addRoute(int pointer, PointerRoute route) {
List<PointerRoute> routes = _routeMap.putIfAbsent(pointer, () => new List<PointerRoute>()); List<PointerRoute> routes = _routeMap.putIfAbsent(pointer, () => new List<PointerRoute>());
...@@ -21,9 +21,9 @@ class PointerRouter { ...@@ -21,9 +21,9 @@ class PointerRouter {
routes.add(route); routes.add(route);
} }
/// Removes a route from the routing table /// Removes a route from the routing table.
/// ///
/// No longer call route when routing a [PointerInputEvent] corresponding to /// No longer call route when routing a [PointerEvent] corresponding to
/// pointer. Requires that this route was previously added to the router. /// pointer. Requires that this route was previously added to the router.
void removeRoute(int pointer, PointerRoute route) { void removeRoute(int pointer, PointerRoute route) {
assert(_routeMap.containsKey(pointer)); assert(_routeMap.containsKey(pointer));
...@@ -37,7 +37,7 @@ class PointerRouter { ...@@ -37,7 +37,7 @@ class PointerRouter {
/// Call the routes registed for this pointer event. /// Call the routes registed for this pointer event.
/// ///
/// Calls the routes in the order in which they were added to the route. /// Calls the routes in the order in which they were added to the route.
void route(PointerInputEvent event) { void route(PointerEvent event) {
List<PointerRoute> routes = _routeMap[event.pointer]; List<PointerRoute> routes = _routeMap[event.pointer];
if (routes == null) if (routes == null)
return; return;
......
...@@ -18,7 +18,7 @@ abstract class GestureRecognizer extends GestureArenaMember { ...@@ -18,7 +18,7 @@ abstract class GestureRecognizer extends GestureArenaMember {
/// considered for this gesture. (It's the GestureRecognizer's responsibility /// considered for this gesture. (It's the GestureRecognizer's responsibility
/// to then add itself to the global pointer router to receive subsequent /// to then add itself to the global pointer router to receive subsequent
/// events for this pointer.) /// events for this pointer.)
void addPointer(PointerInputEvent event); void addPointer(PointerDownEvent event);
/// Release any resources used by the object. Called when the object is no /// Release any resources used by the object. Called when the object is no
/// longer needed (e.g. a gesture recogniser is being unregistered from a /// longer needed (e.g. a gesture recogniser is being unregistered from a
...@@ -34,10 +34,10 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -34,10 +34,10 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
PointerRouter _router; PointerRouter _router;
final List<GestureArenaEntry> _entries = new List<GestureArenaEntry>(); final List<GestureArenaEntry> _entries = <GestureArenaEntry>[];
final Set<int> _trackedPointers = new Set<int>(); final Set<int> _trackedPointers = new Set<int>();
void handleEvent(PointerInputEvent event); void handleEvent(PointerEvent event);
void acceptGesture(int pointer) { } void acceptGesture(int pointer) { }
void rejectGesture(int pointer) { } void rejectGesture(int pointer) { }
void didStopTrackingLastPointer(int pointer); void didStopTrackingLastPointer(int pointer);
...@@ -71,8 +71,8 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -71,8 +71,8 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
didStopTrackingLastPointer(pointer); didStopTrackingLastPointer(pointer);
} }
void stopTrackingIfPointerNoLongerDown(PointerInputEvent event) { void stopTrackingIfPointerNoLongerDown(PointerEvent event) {
if (event.type == 'pointerup' || event.type == 'pointercancel') if (event is PointerUpEvent || event is PointerCancelEvent)
stopTrackingPointer(event.pointer); stopTrackingPointer(event.pointer);
} }
...@@ -95,7 +95,7 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni ...@@ -95,7 +95,7 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni
Point initialPosition; Point initialPosition;
Timer _timer; Timer _timer;
void addPointer(PointerInputEvent event) { void addPointer(PointerDownEvent event) {
startTrackingPointer(event.pointer); startTrackingPointer(event.pointer);
if (state == GestureRecognizerState.ready) { if (state == GestureRecognizerState.ready) {
state = GestureRecognizerState.possible; state = GestureRecognizerState.possible;
...@@ -106,11 +106,11 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni ...@@ -106,11 +106,11 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni
} }
} }
void handleEvent(PointerInputEvent event) { void handleEvent(PointerEvent event) {
assert(state != GestureRecognizerState.ready); assert(state != GestureRecognizerState.ready);
if (state == GestureRecognizerState.possible && event.pointer == primaryPointer) { if (state == GestureRecognizerState.possible && event.pointer == primaryPointer) {
// TODO(abarth): Maybe factor the slop handling out into a separate class? // TODO(abarth): Maybe factor the slop handling out into a separate class?
if (event.type == 'pointermove' && _getDistance(event) > kTouchSlop) { if (event is PointerMoveEvent && _getDistance(event) > kTouchSlop) {
resolve(GestureDisposition.rejected); resolve(GestureDisposition.rejected);
stopTrackingPointer(primaryPointer); stopTrackingPointer(primaryPointer);
} else { } else {
...@@ -121,7 +121,7 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni ...@@ -121,7 +121,7 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni
} }
/// Override to provide behavior for the primary pointer when the gesture is still possible. /// Override to provide behavior for the primary pointer when the gesture is still possible.
void handlePrimaryPointer(PointerInputEvent event); void handlePrimaryPointer(PointerEvent event);
/// Override to be notified with [deadline] is exceeded. /// Override to be notified with [deadline] is exceeded.
/// ///
...@@ -154,7 +154,7 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni ...@@ -154,7 +154,7 @@ abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecogni
} }
} }
double _getDistance(PointerInputEvent event) { double _getDistance(PointerEvent event) {
Offset offset = event.position - initialPosition; Offset offset = event.position - initialPosition;
return offset.distance; return offset.distance;
} }
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:ui' as ui;
import 'arena.dart'; import 'arena.dart';
import 'recognizer.dart'; import 'recognizer.dart';
import 'constants.dart'; import 'constants.dart';
...@@ -16,8 +14,8 @@ enum ScaleState { ...@@ -16,8 +14,8 @@ enum ScaleState {
started started
} }
typedef void GestureScaleStartCallback(ui.Point focalPoint); typedef void GestureScaleStartCallback(Point focalPoint);
typedef void GestureScaleUpdateCallback(double scale, ui.Point focalPoint); typedef void GestureScaleUpdateCallback(double scale, Point focalPoint);
typedef void GestureScaleEndCallback(); typedef void GestureScaleEndCallback();
class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
...@@ -32,35 +30,31 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -32,35 +30,31 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
double _initialSpan; double _initialSpan;
double _currentSpan; double _currentSpan;
Map<int, ui.Point> _pointerLocations; Map<int, Point> _pointerLocations;
double get _scaleFactor => _initialSpan > 0.0 ? _currentSpan / _initialSpan : 1.0; double get _scaleFactor => _initialSpan > 0.0 ? _currentSpan / _initialSpan : 1.0;
void addPointer(PointerInputEvent event) { void addPointer(PointerEvent event) {
startTrackingPointer(event.pointer); startTrackingPointer(event.pointer);
if (_state == ScaleState.ready) { if (_state == ScaleState.ready) {
_state = ScaleState.possible; _state = ScaleState.possible;
_initialSpan = 0.0; _initialSpan = 0.0;
_currentSpan = 0.0; _currentSpan = 0.0;
_pointerLocations = new Map<int, ui.Point>(); _pointerLocations = new Map<int, Point>();
} }
} }
void handleEvent(PointerInputEvent event) { void handleEvent(PointerEvent event) {
assert(_state != ScaleState.ready); assert(_state != ScaleState.ready);
bool configChanged = false; bool configChanged = false;
switch(event.type) { if (event is PointerMoveEvent) {
case 'pointerup': _pointerLocations[event.pointer] = event.position;
configChanged = true; } else if (event is PointerDownEvent) {
_pointerLocations.remove(event.pointer); configChanged = true;
break; _pointerLocations[event.pointer] = event.position;
case 'pointerdown': } else if (event is PointerUpEvent) {
configChanged = true; configChanged = true;
_pointerLocations[event.pointer] = new ui.Point(event.x, event.y); _pointerLocations.remove(event.pointer);
break;
case 'pointermove':
_pointerLocations[event.pointer] = new ui.Point(event.x, event.y);
break;
} }
_update(configChanged); _update(configChanged);
...@@ -72,10 +66,10 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { ...@@ -72,10 +66,10 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
int count = _pointerLocations.keys.length; int count = _pointerLocations.keys.length;
// Compute the focal point // Compute the focal point
ui.Point focalPoint = ui.Point.origin; Point focalPoint = Point.origin;
for (int pointer in _pointerLocations.keys) for (int pointer in _pointerLocations.keys)
focalPoint += _pointerLocations[pointer].toOffset(); focalPoint += _pointerLocations[pointer].toOffset();
focalPoint = new ui.Point(focalPoint.x / count, focalPoint.y / count); focalPoint = new Point(focalPoint.x / count, focalPoint.y / count);
// Span is the average deviation from focal point // Span is the average deviation from focal point
double totalDeviation = 0.0; double totalDeviation = 0.0;
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:ui' show Point, Offset;
import 'arena.dart'; import 'arena.dart';
import 'constants.dart'; import 'constants.dart';
import 'events.dart'; import 'events.dart';
...@@ -36,8 +34,8 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer { ...@@ -36,8 +34,8 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
bool _wonArena = false; bool _wonArena = false;
Point _finalPosition; Point _finalPosition;
void handlePrimaryPointer(PointerInputEvent event) { void handlePrimaryPointer(PointerEvent event) {
if (event.type == 'pointerup') { if (event is PointerUpEvent) {
_finalPosition = event.position; _finalPosition = event.position;
_checkUp(); _checkUp();
} }
......
...@@ -2,17 +2,11 @@ ...@@ -2,17 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:ui' as ui; import 'dart:ui' show Point, Offset;
import 'lsq_solver.dart'; import 'lsq_solver.dart';
class GestureVelocity { export 'dart:ui' show Point, Offset;
GestureVelocity({ this.isValid: false, this.x: 0.0, this.y : 0.0 });
final bool isValid;
final double x;
final double y;
}
class _Estimator { class _Estimator {
int degree; int degree;
...@@ -22,17 +16,16 @@ class _Estimator { ...@@ -22,17 +16,16 @@ class _Estimator {
double confidence; double confidence;
String toString() { String toString() {
String result = "Estimator(degree: " + degree.toString(); return 'Estimator(degree: $degree, '
result += ", time: " + time.toString(); 'time: $time, '
result += ", confidence: " + confidence.toString(); 'confidence: $confidence, '
result += ", xCoefficients: " + xCoefficients.toString(); 'xCoefficients: $xCoefficients, '
result += ", yCoefficients: " + yCoefficients.toString(); 'yCoefficients: $yCoefficients)';
return result;
} }
} }
abstract class _VelocityTrackerStrategy { abstract class _VelocityTrackerStrategy {
void addMovement(Duration timeStamp, double x, double y); void addMovement(Duration timeStamp, Point position);
bool getEstimator(_Estimator estimator); bool getEstimator(_Estimator estimator);
void clear(); void clear();
} }
...@@ -45,28 +38,46 @@ enum _Weighting { ...@@ -45,28 +38,46 @@ enum _Weighting {
} }
class _Movement { class _Movement {
Duration eventTime = const Duration(); Duration eventTime = Duration.ZERO;
ui.Point position = ui.Point.origin; Point position = Point.origin;
} }
typedef double _WeightChooser(int index);
class _LeastSquaresVelocityTrackerStrategy extends _VelocityTrackerStrategy { class _LeastSquaresVelocityTrackerStrategy extends _VelocityTrackerStrategy {
static const int kHistorySize = 20; static const int kHistorySize = 20;
static const int kHorizonMilliseconds = 100; static const int kHorizonMilliseconds = 100;
_LeastSquaresVelocityTrackerStrategy(this.degree, this.weighting) _LeastSquaresVelocityTrackerStrategy(this.degree, _Weighting weighting)
: _index = 0, _movements = new List<_Movement>(kHistorySize); : _index = 0, _movements = new List<_Movement>(kHistorySize) {
switch (weighting) {
case _Weighting.weightingNone:
_chooseWeight = null;
break;
case _Weighting.weightingDelta:
_chooseWeight = _weightDelta;
break;
case _Weighting.weightingCentral:
_chooseWeight = _weightCentral;
break;
case _Weighting.weightingRecent:
_chooseWeight = _weightRecent;
break;
}
}
final int degree; final int degree;
final _Weighting weighting;
final List<_Movement> _movements; final List<_Movement> _movements;
_WeightChooser _chooseWeight;
int _index; int _index;
void addMovement(Duration timeStamp, double x, double y) { void addMovement(Duration timeStamp, Point position) {
if (++_index == kHistorySize) _index += 1;
if (_index == kHistorySize)
_index = 0; _index = 0;
_Movement movement = _getMovement(_index); _Movement movement = _getMovement(_index);
movement.eventTime = timeStamp; movement.eventTime = timeStamp;
movement.position = new ui.Point(x, y); movement.position = position;
} }
bool getEstimator(_Estimator estimator) { bool getEstimator(_Estimator estimator) {
...@@ -85,16 +96,18 @@ class _LeastSquaresVelocityTrackerStrategy extends _VelocityTrackerStrategy { ...@@ -85,16 +96,18 @@ class _LeastSquaresVelocityTrackerStrategy extends _VelocityTrackerStrategy {
if (age > kHorizonMilliseconds) if (age > kHorizonMilliseconds)
break; break;
ui.Point position = movement.position; Point position = movement.position;
x.add(position.x); x.add(position.x);
y.add(position.y); y.add(position.y);
w.add(_chooseWeight(index)); w.add(_chooseWeight != null ? _chooseWeight(index) : 1.0);
time.add(-age); time.add(-age);
index = (index == 0 ? kHistorySize : index) - 1; index = (index == 0 ? kHistorySize : index) - 1;
} while (++m < kHistorySize);
if (m == 0) m += 1;
return false; // no data } while (m < kHistorySize);
if (m == 0) // because we broke out of the loop above after age > kHorizonMilliseconds
return false; // no data
// Calculate a least squares polynomial fit. // Calculate a least squares polynomial fit.
int n = degree; int n = degree;
...@@ -120,8 +133,8 @@ class _LeastSquaresVelocityTrackerStrategy extends _VelocityTrackerStrategy { ...@@ -120,8 +133,8 @@ class _LeastSquaresVelocityTrackerStrategy extends _VelocityTrackerStrategy {
// No velocity data available for this pointer, but we do have its current // No velocity data available for this pointer, but we do have its current
// position. // position.
estimator.xCoefficients = [ x[0] ]; estimator.xCoefficients = <double>[ x[0] ];
estimator.yCoefficients = [ y[0] ]; estimator.yCoefficients = <double>[ y[0] ];
estimator.time = newestMovement.eventTime; estimator.time = newestMovement.eventTime;
estimator.degree = 0; estimator.degree = 0;
estimator.confidence = 1.0; estimator.confidence = 1.0;
...@@ -132,71 +145,61 @@ class _LeastSquaresVelocityTrackerStrategy extends _VelocityTrackerStrategy { ...@@ -132,71 +145,61 @@ class _LeastSquaresVelocityTrackerStrategy extends _VelocityTrackerStrategy {
_index = -1; _index = -1;
} }
double _chooseWeight(int index) { double _weightDelta(int index) {
switch (weighting) { // Weight points based on how much time elapsed between them and the next
case _Weighting.weightingDelta: // point so that points that "cover" a shorter time span are weighed less.
// Weight points based on how much time elapsed between them and the next // delta 0ms: 0.5
// point so that points that "cover" a shorter time span are weighed less. // delta 10ms: 1.0
// delta 0ms: 0.5 if (index == _index)
// delta 10ms: 1.0 return 1.0;
if (index == _index) { int nextIndex = (index + 1) % kHistorySize;
return 1.0; int deltaMilliseconds = (_movements[nextIndex].eventTime - _movements[index].eventTime).inMilliseconds;
} if (deltaMilliseconds < 0)
int nextIndex = (index + 1) % kHistorySize; return 0.5;
int deltaMilliseconds = (_movements[nextIndex].eventTime - _movements[index].eventTime).inMilliseconds; if (deltaMilliseconds < 10)
if (deltaMilliseconds < 0) return 0.5 + deltaMilliseconds * 0.05;
return 0.5; return 1.0;
if (deltaMilliseconds < 10) }
return 0.5 + deltaMilliseconds * 0.05;
return 1.0;
case _Weighting.weightingCentral:
// Weight points based on their age, weighing very recent and very old
// points less.
// age 0ms: 0.5
// age 10ms: 1.0
// age 50ms: 1.0
// age 60ms: 0.5
int ageMilliseconds = (_movements[_index].eventTime - _movements[index].eventTime).inMilliseconds;
if (ageMilliseconds < 0)
return 0.5;
if (ageMilliseconds < 10)
return 0.5 + ageMilliseconds * 0.05;
if (ageMilliseconds < 50)
return 1.0;
if (ageMilliseconds < 60)
return 0.5 + (60 - ageMilliseconds) * 0.05;
return 0.5;
case _Weighting.weightingRecent: double _weightCentral(int index) {
// Weight points based on their age, weighing older points less. // Weight points based on their age, weighing very recent and very old
// age 0ms: 1.0 // points less.
// age 50ms: 1.0 // age 0ms: 0.5
// age 100ms: 0.5 // age 10ms: 1.0
int ageMilliseconds = (_movements[_index].eventTime - _movements[index].eventTime).inMilliseconds; // age 50ms: 1.0
if (ageMilliseconds < 50) { // age 60ms: 0.5
return 1.0; int ageMilliseconds = (_movements[_index].eventTime - _movements[index].eventTime).inMilliseconds;
} if (ageMilliseconds < 0)
if (ageMilliseconds < 100) { return 0.5;
return 0.5 + (100 - ageMilliseconds) * 0.01; if (ageMilliseconds < 10)
} return 0.5 + ageMilliseconds * 0.05;
return 0.5; if (ageMilliseconds < 50)
return 1.0;
if (ageMilliseconds < 60)
return 0.5 + (60 - ageMilliseconds) * 0.05;
return 0.5;
}
case _Weighting.weightingNone: double _weightRecent(int index) {
default: // Weight points based on their age, weighing older points less.
return 1.0; // age 0ms: 1.0
} // age 50ms: 1.0
// age 100ms: 0.5
int ageMilliseconds = (_movements[_index].eventTime - _movements[index].eventTime).inMilliseconds;
if (ageMilliseconds < 50)
return 1.0;
if (ageMilliseconds < 100)
return 0.5 + (100 - ageMilliseconds) * 0.01;
return 0.5;
} }
_Movement _getMovement(int i) { _Movement _getMovement(int i) {
_Movement result = _movements[i]; _Movement result = _movements[i];
if (result == null) { if (result == null) {
result = new _Movement(); result = new _Movement();
_movements[i] = result; _movements[i] = result;
} }
return result; return result;
} }
} }
...@@ -209,24 +212,22 @@ class VelocityTracker { ...@@ -209,24 +212,22 @@ class VelocityTracker {
Duration _lastTimeStamp = const Duration(); Duration _lastTimeStamp = const Duration();
_VelocityTrackerStrategy _strategy; _VelocityTrackerStrategy _strategy;
void addPosition(Duration timeStamp, double x, double y) { void addPosition(Duration timeStamp, Point position) {
if ((timeStamp - _lastTimeStamp).inMilliseconds >= kAssumePointerMoveStoppedTimeMs) if ((timeStamp - _lastTimeStamp).inMilliseconds >= kAssumePointerMoveStoppedTimeMs)
_strategy.clear(); _strategy.clear();
_lastTimeStamp = timeStamp; _lastTimeStamp = timeStamp;
_strategy.addMovement(timeStamp, x, y); _strategy.addMovement(timeStamp, position);
} }
GestureVelocity getVelocity() { Offset getVelocity() {
_Estimator estimator = new _Estimator(); _Estimator estimator = new _Estimator();
if (_strategy.getEstimator(estimator) && estimator.degree >= 1) { if (_strategy.getEstimator(estimator) && estimator.degree >= 1) {
// convert from pixels/ms to pixels/s return new Offset( // convert from pixels/ms to pixels/s
return new GestureVelocity( estimator.xCoefficients[1] * 1000,
isValid: true, estimator.yCoefficients[1] * 1000
x: estimator.xCoefficients[1] * 1000,
y: estimator.yCoefficients[1] * 1000
); );
} }
return new GestureVelocity(isValid: false, x: 0.0, y: 0.0); return null;
} }
static _VelocityTrackerStrategy _createStrategy() { static _VelocityTrackerStrategy _createStrategy() {
......
...@@ -148,8 +148,8 @@ class _RenderSlider extends RenderConstrainedBox { ...@@ -148,8 +148,8 @@ class _RenderSlider extends RenderConstrainedBox {
bool hitTestSelf(Point position) => true; bool hitTestSelf(Point position) => true;
void handleEvent(InputEvent event, BoxHitTestEntry entry) { void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
if (event.type == 'pointerdown' && onChanged != null) if (event is PointerDownEvent && onChanged != null)
_drag.addPointer(event); _drag.addPointer(event);
} }
......
...@@ -164,8 +164,8 @@ class _RenderSwitch extends RenderToggleable { ...@@ -164,8 +164,8 @@ class _RenderSwitch extends RenderToggleable {
reaction.reverse(); reaction.reverse();
} }
void handleEvent(InputEvent event, BoxHitTestEntry entry) { void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
if (event.type == 'pointerdown' && onChanged != null) if (event is PointerDownEvent && onChanged != null)
_drag.addPointer(event); _drag.addPointer(event);
super.handleEvent(event, entry); super.handleEvent(event, entry);
} }
......
...@@ -122,8 +122,8 @@ abstract class RenderToggleable extends RenderConstrainedBox { ...@@ -122,8 +122,8 @@ abstract class RenderToggleable extends RenderConstrainedBox {
bool hitTestSelf(Point position) => true; bool hitTestSelf(Point position) => true;
void handleEvent(InputEvent event, BoxHitTestEntry entry) { void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
if (event.type == 'pointerdown' && isInteractive) if (event is PointerDownEvent && isInteractive)
_tap.addPointer(event); _tap.addPointer(event);
} }
......
...@@ -636,14 +636,15 @@ abstract class RenderBox extends RenderObject { ...@@ -636,14 +636,15 @@ abstract class RenderBox extends RenderObject {
Rect get paintBounds => Point.origin & size; Rect get paintBounds => Point.origin & size;
int _debugActivePointers = 0; int _debugActivePointers = 0;
void handleEvent(InputEvent event, HitTestEntry entry) { void handleEvent(PointerEvent event, HitTestEntry entry) {
super.handleEvent(event, entry); super.handleEvent(event, entry);
assert(() { assert(() {
if (debugPaintPointersEnabled) { if (debugPaintPointersEnabled) {
if (event.type == 'pointerdown') if (event is PointerDownEvent) {
_debugActivePointers += 1; _debugActivePointers += 1;
if (event.type == 'pointerup' || event.type == 'pointercancel') } else if (event is PointerUpEvent || event is PointerCancelEvent) {
_debugActivePointers -= 1; _debugActivePointers -= 1;
}
markNeedsPaint(); markNeedsPaint();
} }
return true; return true;
......
...@@ -7,7 +7,7 @@ import 'package:flutter/gestures.dart'; ...@@ -7,7 +7,7 @@ import 'package:flutter/gestures.dart';
/// An object that can handle events. /// An object that can handle events.
abstract class HitTestTarget { abstract class HitTestTarget {
/// Override this function to receive events. /// Override this function to receive events.
void handleEvent(InputEvent event, HitTestEntry entry); void handleEvent(PointerEvent event, HitTestEntry entry);
} }
/// Data collected during a hit test about a specific [HitTestTarget]. /// Data collected during a hit test about a specific [HitTestTarget].
......
...@@ -1045,8 +1045,8 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { ...@@ -1045,8 +1045,8 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
// EVENTS // EVENTS
/// Override this function to handle events that hit this render object /// Override this function to handle pointer events that hit this render object.
void handleEvent(InputEvent event, HitTestEntry entry) { } void handleEvent(PointerEvent event, HitTestEntry entry) { }
// HIT TESTING // HIT TESTING
......
...@@ -1072,7 +1072,10 @@ class RenderCustomPaint extends RenderProxyBox { ...@@ -1072,7 +1072,10 @@ class RenderCustomPaint extends RenderProxyBox {
} }
} }
typedef void PointerEventListener(PointerInputEvent event); typedef void PointerDownEventListener(PointerDownEvent event);
typedef void PointerMoveEventListener(PointerMoveEvent event);
typedef void PointerUpEventListener(PointerUpEvent event);
typedef void PointerCancelEventListener(PointerCancelEvent event);
enum HitTestBehavior { enum HitTestBehavior {
deferToChild, deferToChild,
...@@ -1091,10 +1094,10 @@ class RenderPointerListener extends RenderProxyBox { ...@@ -1091,10 +1094,10 @@ class RenderPointerListener extends RenderProxyBox {
RenderBox child RenderBox child
}) : super(child); }) : super(child);
PointerEventListener onPointerDown; PointerDownEventListener onPointerDown;
PointerEventListener onPointerMove; PointerMoveEventListener onPointerMove;
PointerEventListener onPointerUp; PointerUpEventListener onPointerUp;
PointerEventListener onPointerCancel; PointerCancelEventListener onPointerCancel;
HitTestBehavior behavior; HitTestBehavior behavior;
bool hitTest(HitTestResult result, { Point position }) { bool hitTest(HitTestResult result, { Point position }) {
...@@ -1110,14 +1113,14 @@ class RenderPointerListener extends RenderProxyBox { ...@@ -1110,14 +1113,14 @@ class RenderPointerListener extends RenderProxyBox {
bool hitTestSelf(Point position) => behavior == HitTestBehavior.opaque; bool hitTestSelf(Point position) => behavior == HitTestBehavior.opaque;
void handleEvent(InputEvent event, HitTestEntry entry) { void handleEvent(PointerEvent event, HitTestEntry entry) {
if (onPointerDown != null && event.type == 'pointerdown') if (onPointerDown != null && event is PointerDownEvent)
return onPointerDown(event); return onPointerDown(event);
if (onPointerMove != null && event.type == 'pointermove') if (onPointerMove != null && event == PointerMoveEvent)
return onPointerMove(event); return onPointerMove(event);
if (onPointerUp != null && event.type == 'pointerup') if (onPointerUp != null && event == PointerUpEvent)
return onPointerUp(event); return onPointerUp(event);
if (onPointerCancel != null && event.type == 'pointercancel') if (onPointerCancel != null && event == PointerCancelEvent)
return onPointerCancel(event); return onPointerCancel(event);
} }
......
...@@ -1299,10 +1299,10 @@ class Listener extends OneChildRenderObjectWidget { ...@@ -1299,10 +1299,10 @@ class Listener extends OneChildRenderObjectWidget {
assert(behavior != null); assert(behavior != null);
} }
final PointerEventListener onPointerDown; final PointerDownEventListener onPointerDown;
final PointerEventListener onPointerMove; final PointerMoveEventListener onPointerMove;
final PointerEventListener onPointerUp; final PointerUpEventListener onPointerUp;
final PointerEventListener onPointerCancel; final PointerCancelEventListener onPointerCancel;
final HitTestBehavior behavior; final HitTestBehavior behavior;
RenderPointerListener createRenderObject() => new RenderPointerListener( RenderPointerListener createRenderObject() => new RenderPointerListener(
......
...@@ -135,7 +135,7 @@ class _DraggableState<T> extends State<DraggableBase<T>> implements GestureArena ...@@ -135,7 +135,7 @@ class _DraggableState<T> extends State<DraggableBase<T>> implements GestureArena
GestureRecognizer _recognizer; GestureRecognizer _recognizer;
Map<int, GestureArenaEntry> _activePointers = <int, GestureArenaEntry>{}; Map<int, GestureArenaEntry> _activePointers = <int, GestureArenaEntry>{};
void _routePointer(PointerInputEvent event) { void _routePointer(PointerEvent event) {
_activePointers[event.pointer] = GestureArena.instance.add(event.pointer, this); _activePointers[event.pointer] = GestureArena.instance.add(event.pointer, this);
_recognizer.addPointer(event); _recognizer.addPointer(event);
} }
...@@ -284,18 +284,14 @@ class _DragAvatar<T> { ...@@ -284,18 +284,14 @@ class _DragAvatar<T> {
Offset _lastOffset; Offset _lastOffset;
OverlayEntry _entry; OverlayEntry _entry;
void handleEvent(PointerInputEvent event) { void handleEvent(PointerEvent event) {
switch(event.type) { if (event is PointerUpEvent) {
case 'pointerup': update(event.position);
update(event.position); finish(_DragEndKind.dropped);
finish(_DragEndKind.dropped); } else if (event is PointerCancelEvent) {
break; finish(_DragEndKind.canceled);
case 'pointercancel': } else if (event is PointerMoveEvent) {
finish(_DragEndKind.canceled); update(event.position);
break;
case 'pointermove':
update(event.position);
break;
} }
} }
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'basic.dart'; import 'basic.dart';
import 'framework.dart'; import 'framework.dart';
...@@ -13,7 +12,7 @@ enum EventRecorderMode { ...@@ -13,7 +12,7 @@ enum EventRecorderMode {
record record
} }
typedef void EventsReadyCallback(List<PointerInputEvent> events); typedef void EventsReadyCallback(Iterable<PointerEvent> events);
/// EventRecorder is a utility widget that allows input events occurring /// EventRecorder is a utility widget that allows input events occurring
/// on the child to be recorded. The widget is initially in the "stop" state /// on the child to be recorded. The widget is initially in the "stop" state
...@@ -38,11 +37,7 @@ class EventRecorder extends StatefulComponent { ...@@ -38,11 +37,7 @@ class EventRecorder extends StatefulComponent {
class _EventRecorderState extends State<EventRecorder> { class _EventRecorderState extends State<EventRecorder> {
List<PointerInputEvent> _events = new List<PointerInputEvent>(); final List<PointerEvent> _events = <PointerEvent>[];
void initState() {
super.initState();
}
void didUpdateConfig(EventRecorder oldConfig) { void didUpdateConfig(EventRecorder oldConfig) {
if (oldConfig.mode == EventRecorderMode.record && if (oldConfig.mode == EventRecorderMode.record &&
...@@ -52,10 +47,9 @@ class _EventRecorderState extends State<EventRecorder> { ...@@ -52,10 +47,9 @@ class _EventRecorderState extends State<EventRecorder> {
} }
} }
void _recordEvent(PointerInputEvent event) { void _recordEvent(PointerEvent event) {
if (config.mode == EventRecorderMode.record) { if (config.mode == EventRecorderMode.record)
_events.add(event); _events.add(event);
}
} }
Widget build(BuildContext context) { Widget build(BuildContext context) {
......
...@@ -210,7 +210,7 @@ class _GestureDetectorState extends State<GestureDetector> { ...@@ -210,7 +210,7 @@ class _GestureDetectorState extends State<GestureDetector> {
return null; return null;
} }
void _handlePointerDown(PointerInputEvent event) { void _handlePointerDown(PointerDownEvent event) {
if (_tap != null) if (_tap != null)
_tap.addPointer(event); _tap.addPointer(event);
if (_doubleTap != null) if (_doubleTap != null)
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:ui' as ui;
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
export 'dart:ui' show Point; export 'dart:ui' show Point;
...@@ -13,57 +11,48 @@ class TestPointer { ...@@ -13,57 +11,48 @@ class TestPointer {
int pointer; int pointer;
bool isDown = false; bool isDown = false;
ui.Point location; Point location;
PointerInputEvent down(ui.Point newLocation, { Duration timeStamp: const Duration() }) { PointerDownEvent down(Point newLocation, { Duration timeStamp: const Duration() }) {
assert(!isDown); assert(!isDown);
isDown = true; isDown = true;
location = newLocation; location = newLocation;
return new PointerInputEvent( return new PointerDownEvent(
type: 'pointerdown', timeStamp: timeStamp,
pointer: pointer, pointer: pointer,
x: location.x, position: location
y: location.y,
timeStamp: timeStamp
); );
} }
PointerInputEvent move(ui.Point newLocation, { Duration timeStamp: const Duration() }) { PointerMoveEvent move(Point newLocation, { Duration timeStamp: const Duration() }) {
assert(isDown); assert(isDown);
ui.Offset delta = newLocation - location; Offset delta = newLocation - location;
location = newLocation; location = newLocation;
return new PointerInputEvent( return new PointerMoveEvent(
type: 'pointermove', timeStamp: timeStamp,
pointer: pointer, pointer: pointer,
x: newLocation.x, position: newLocation,
y: newLocation.y, delta: delta
dx: delta.dx,
dy: delta.dy,
timeStamp: timeStamp
); );
} }
PointerInputEvent up({ Duration timeStamp: const Duration() }) { PointerUpEvent up({ Duration timeStamp: const Duration() }) {
assert(isDown); assert(isDown);
isDown = false; isDown = false;
return new PointerInputEvent( return new PointerUpEvent(
type: 'pointerup', timeStamp: timeStamp,
pointer: pointer, pointer: pointer,
x: location.x, position: location
y: location.y,
timeStamp: timeStamp
); );
} }
PointerInputEvent cancel({ Duration timeStamp: const Duration() }) { PointerCancelEvent cancel({ Duration timeStamp: const Duration() }) {
assert(isDown); assert(isDown);
isDown = false; isDown = false;
return new PointerInputEvent( return new PointerCancelEvent(
type: 'pointercancel', timeStamp: timeStamp,
pointer: pointer, pointer: pointer,
x: location.x, position: location
y: location.y,
timeStamp: timeStamp
); );
} }
......
...@@ -174,13 +174,13 @@ class WidgetTester { ...@@ -174,13 +174,13 @@ class WidgetTester {
_dispatchEvent(p.up(), result); _dispatchEvent(p.up(), result);
} }
void dispatchEvent(InputEvent event, Point location) { void dispatchEvent(PointerEvent event, Point location) {
_dispatchEvent(event, _hitTest(location)); _dispatchEvent(event, _hitTest(location));
} }
HitTestResult _hitTest(Point location) => WidgetFlutterBinding.instance.hitTest(location); HitTestResult _hitTest(Point location) => WidgetFlutterBinding.instance.hitTest(location);
void _dispatchEvent(InputEvent event, HitTestResult result) { void _dispatchEvent(PointerEvent event, HitTestResult result) {
WidgetFlutterBinding.instance.dispatchEvent(event, result); WidgetFlutterBinding.instance.dispatchEvent(event, result);
} }
......
# Benchmarks # Benchmarks
This directory (and its sub-directories) contain benchmarks for Flutter. This directory (and its sub-directories) contain benchmarks for
The reporting format for benchmarks is not standardized yet, so benchmarks Flutter. The reporting format for benchmarks is not standardized yet,
here are typically run by hand. To run a benchmark: so benchmarks here are typically run by hand. To run a benchmark:
1. Build `sky_shell` for Linux Release using the instructions in the 1. Build `sky_shell` for Linux Release using the instructions in the
[Engine repository](https://github.com/flutter/engine). [Engine repository](https://github.com/flutter/engine).
2. Run `pub get` in the `packages/unit` directory. 2. Run `pub get` in the `packages/unit` directory.
3. Run the benchmark: 3. Run the benchmarks by running the following command from the root
of the flutter repository (replacing `stocks/layout_bench.dart`
with the path to whichever benchmark you want to run):
``` ```
/path/to/engine/src/out/Release/sky_shell packages/unit/benchmark/stocks/layout_bench.dart --package-root=packages/unit/package /path/to/engine/src/out/Release/sky_shell packages/unit/benchmark/stocks/layout_bench.dart --package-root=packages/unit/packages
``` ```
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'velocity_tracker_data.dart'; import 'velocity_tracker_data.dart';
...@@ -7,36 +11,16 @@ const int kBatchSize = 1000; ...@@ -7,36 +11,16 @@ const int kBatchSize = 1000;
const int kBatchOffset = 50; const int kBatchOffset = 50;
const int kNumMarks = 130; const int kNumMarks = 130;
List<PointerInputEvent> _eventFromMap(List<Map> intermediate) {
List<PointerInputEvent> events = new List<PointerInputEvent>();
for (Map entry in intermediate)
events.add(_eventFor(entry));
return events;
}
PointerInputEvent _eventFor(Map entry) {
PointerInputEvent result = new PointerInputEvent(
type: entry['type'],
timeStamp: entry['timeStamp'],
pointer: entry['pointer'],
x: entry['x'],
y: entry['y']
);
return result;
}
void main() { void main() {
List<PointerInputEvent> events = _eventFromMap(velocityEventData);
test('Dart velocity tracker performance', () { test('Dart velocity tracker performance', () {
VelocityTracker tracker = new VelocityTracker(); VelocityTracker tracker = new VelocityTracker();
Stopwatch watch = new Stopwatch(); Stopwatch watch = new Stopwatch();
watch.start(); watch.start();
for (int i = 0; i < kNumIters; i++) { for (int i = 0; i < kNumIters; i++) {
for (PointerInputEvent event in events) { for (PointerEvent event in velocityEventData) {
if (event.type == 'pointerdown' || event.type == 'pointermove') if (event is PointerDownEvent || event is PointerMoveEvent)
tracker.addPosition(event.timeStamp, event.x, event.y); tracker.addPosition(event.timeStamp, event.position);
if (event.type == 'pointerup') if (event is PointerUpEvent)
tracker.getVelocity(); tracker.getVelocity();
} }
} }
......
...@@ -16,85 +16,63 @@ class TestGestureArenaMember extends GestureArenaMember { ...@@ -16,85 +16,63 @@ class TestGestureArenaMember extends GestureArenaMember {
void main() { void main() {
// Down/up pair 1: normal tap sequence // Down/up pair 1: normal tap sequence
final PointerInputEvent down1 = new PointerInputEvent( const PointerDownEvent down1 = const PointerDownEvent(
pointer: 1, pointer: 1,
type: 'pointerdown', position: const Point(10.0, 10.0)
x: 10.0,
y: 10.0
); );
final PointerInputEvent up1 = new PointerInputEvent( const PointerUpEvent up1 = const PointerUpEvent(
pointer: 1, pointer: 1,
type: 'pointerup', position: const Point(11.0, 9.0)
x: 11.0,
y: 9.0
); );
// Down/up pair 2: normal tap sequence close to pair 1 // Down/up pair 2: normal tap sequence close to pair 1
final PointerInputEvent down2 = new PointerInputEvent( const PointerDownEvent down2 = const PointerDownEvent(
pointer: 2, pointer: 2,
type: 'pointerdown', position: const Point(12.0, 12.0)
x: 12.0,
y: 12.0
); );
final PointerInputEvent up2 = new PointerInputEvent( const PointerUpEvent up2 = const PointerUpEvent(
pointer: 2, pointer: 2,
type: 'pointerup', position: const Point(13.0, 11.0)
x: 13.0,
y: 11.0
); );
// Down/up pair 3: normal tap sequence far away from pair 1 // Down/up pair 3: normal tap sequence far away from pair 1
final PointerInputEvent down3 = new PointerInputEvent( const PointerDownEvent down3 = const PointerDownEvent(
pointer: 3, pointer: 3,
type: 'pointerdown', position: const Point(130.0, 130.0)
x: 130.0,
y: 130.0
); );
final PointerInputEvent up3 = new PointerInputEvent( const PointerUpEvent up3 = const PointerUpEvent(
pointer: 3, pointer: 3,
type: 'pointerup', position: const Point(131.0, 129.0)
x: 131.0,
y: 129.0
); );
// Down/move/up sequence 4: intervening motion // Down/move/up sequence 4: intervening motion
final PointerInputEvent down4 = new PointerInputEvent( const PointerDownEvent down4 = const PointerDownEvent(
pointer: 4, pointer: 4,
type: 'pointerdown', position: const Point(10.0, 10.0)
x: 10.0,
y: 10.0
); );
final PointerInputEvent move4 = new PointerInputEvent( const PointerMoveEvent move4 = const PointerMoveEvent(
pointer: 4, pointer: 4,
type: 'pointermove', position: const Point(25.0, 25.0)
x: 25.0,
y: 25.0
); );
final PointerInputEvent up4 = new PointerInputEvent( const PointerUpEvent up4 = const PointerUpEvent(
pointer: 4, pointer: 4,
type: 'pointerup', position: const Point(25.0, 25.0)
x: 25.0,
y: 25.0
); );
// Down/up pair 5: normal tap sequence identical to pair 1 with different pointer // Down/up pair 5: normal tap sequence identical to pair 1 with different pointer
final PointerInputEvent down5 = new PointerInputEvent( const PointerDownEvent down5 = const PointerDownEvent(
pointer: 5, pointer: 5,
type: 'pointerdown', position: const Point(10.0, 10.0)
x: 10.0,
y: 10.0
); );
final PointerInputEvent up5 = new PointerInputEvent( const PointerUpEvent up5 = const PointerUpEvent(
pointer: 5, pointer: 5,
type: 'pointerup', position: const Point(11.0, 9.0)
x: 11.0,
y: 9.0
); );
test('Should recognize double tap', () { test('Should recognize double tap', () {
...@@ -546,7 +524,7 @@ void main() { ...@@ -546,7 +524,7 @@ void main() {
expect(member.accepted, isFalse); expect(member.accepted, isFalse);
async.elapse(new Duration(milliseconds: 5000)); async.elapse(const Duration(milliseconds: 5000));
expect(member.accepted, isTrue); expect(member.accepted, isTrue);
}); });
......
...@@ -2,18 +2,14 @@ import 'package:quiver/testing/async.dart'; ...@@ -2,18 +2,14 @@ import 'package:quiver/testing/async.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
final PointerInputEvent down = new PointerInputEvent( const PointerDownEvent down = const PointerDownEvent(
pointer: 5, pointer: 5,
type: 'pointerdown', position: const Point(10.0, 10.0)
x: 10.0,
y: 10.0
); );
final PointerInputEvent up = new PointerInputEvent( const PointerUpEvent up = const PointerUpEvent(
pointer: 5, pointer: 5,
type: 'pointerup', position: const Point(11.0, 9.0)
x: 11.0,
y: 9.0
); );
void main() { void main() {
...@@ -32,9 +28,9 @@ void main() { ...@@ -32,9 +28,9 @@ void main() {
expect(longPressRecognized, isFalse); expect(longPressRecognized, isFalse);
router.route(down); router.route(down);
expect(longPressRecognized, isFalse); expect(longPressRecognized, isFalse);
async.elapse(new Duration(milliseconds: 300)); async.elapse(const Duration(milliseconds: 300));
expect(longPressRecognized, isFalse); expect(longPressRecognized, isFalse);
async.elapse(new Duration(milliseconds: 700)); async.elapse(const Duration(milliseconds: 700));
expect(longPressRecognized, isTrue); expect(longPressRecognized, isTrue);
}); });
...@@ -56,11 +52,11 @@ void main() { ...@@ -56,11 +52,11 @@ void main() {
expect(longPressRecognized, isFalse); expect(longPressRecognized, isFalse);
router.route(down); router.route(down);
expect(longPressRecognized, isFalse); expect(longPressRecognized, isFalse);
async.elapse(new Duration(milliseconds: 300)); async.elapse(const Duration(milliseconds: 300));
expect(longPressRecognized, isFalse); expect(longPressRecognized, isFalse);
router.route(up); router.route(up);
expect(longPressRecognized, isFalse); expect(longPressRecognized, isFalse);
async.elapse(new Duration(seconds: 1)); async.elapse(const Duration(seconds: 1));
expect(longPressRecognized, isFalse); expect(longPressRecognized, isFalse);
}); });
...@@ -91,10 +87,10 @@ void main() { ...@@ -91,10 +87,10 @@ void main() {
router.route(down); router.route(down);
expect(tapDownRecognized, isFalse); expect(tapDownRecognized, isFalse);
expect(longPressRecognized, isFalse); expect(longPressRecognized, isFalse);
async.elapse(new Duration(milliseconds: 300)); async.elapse(const Duration(milliseconds: 300));
expect(tapDownRecognized, isTrue); expect(tapDownRecognized, isTrue);
expect(longPressRecognized, isFalse); expect(longPressRecognized, isFalse);
async.elapse(new Duration(milliseconds: 700)); async.elapse(const Duration(milliseconds: 700));
expect(tapDownRecognized, isTrue); expect(tapDownRecognized, isTrue);
expect(longPressRecognized, isTrue); expect(longPressRecognized, isTrue);
}); });
......
...@@ -9,9 +9,9 @@ void main() { ...@@ -9,9 +9,9 @@ void main() {
} }
test('Least-squares fit: linear polynomial to line', () { test('Least-squares fit: linear polynomial to line', () {
List<double> x = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]; List<double> x = <double>[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
List<double> y = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; List<double> y = <double>[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0];
List<double> w = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; List<double> w = <double>[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0];
LeastSquaresSolver solver = new LeastSquaresSolver(x, y, w); LeastSquaresSolver solver = new LeastSquaresSolver(x, y, w);
PolynomialFit fit = solver.solve(1); PolynomialFit fit = solver.solve(1);
...@@ -23,9 +23,9 @@ void main() { ...@@ -23,9 +23,9 @@ void main() {
}); });
test('Least-squares fit: linear polynomial to sloped line', () { test('Least-squares fit: linear polynomial to sloped line', () {
List<double> x = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]; List<double> x = <double>[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
List<double> y = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]; List<double> y = <double>[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
List<double> w = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; List<double> w = <double>[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0];
LeastSquaresSolver solver = new LeastSquaresSolver(x, y, w); LeastSquaresSolver solver = new LeastSquaresSolver(x, y, w);
PolynomialFit fit = solver.solve(1); PolynomialFit fit = solver.solve(1);
...@@ -37,9 +37,9 @@ void main() { ...@@ -37,9 +37,9 @@ void main() {
}); });
test('Least-squares fit: quadratic polynomial to line', () { test('Least-squares fit: quadratic polynomial to line', () {
List<double> x = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]; List<double> x = <double>[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
List<double> y = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; List<double> y = <double>[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0];
List<double> w = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; List<double> w = <double>[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0];
LeastSquaresSolver solver = new LeastSquaresSolver(x, y, w); LeastSquaresSolver solver = new LeastSquaresSolver(x, y, w);
PolynomialFit fit = solver.solve(2); PolynomialFit fit = solver.solve(2);
...@@ -52,9 +52,9 @@ void main() { ...@@ -52,9 +52,9 @@ void main() {
}); });
test('Least-squares fit: quadratic polynomial to sloped line', () { test('Least-squares fit: quadratic polynomial to sloped line', () {
List<double> x = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]; List<double> x = <double>[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
List<double> y = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]; List<double> y = <double>[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
List<double> w = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]; List<double> w = <double>[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0];
LeastSquaresSolver solver = new LeastSquaresSolver(x, y, w); LeastSquaresSolver solver = new LeastSquaresSolver(x, y, w);
PolynomialFit fit = solver.solve(2); PolynomialFit fit = solver.solve(2);
......
...@@ -5,7 +5,7 @@ import 'package:test/test.dart'; ...@@ -5,7 +5,7 @@ import 'package:test/test.dart';
void main() { void main() {
test('Should route pointers', () { test('Should route pointers', () {
bool callbackRan = false; bool callbackRan = false;
void callback(PointerInputEvent event) { void callback(PointerEvent event) {
callbackRan = true; callbackRan = true;
} }
......
import 'dart:ui' as ui;
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
...@@ -11,14 +9,14 @@ void main() { ...@@ -11,14 +9,14 @@ void main() {
TapGestureRecognizer tap = new TapGestureRecognizer(router: router); TapGestureRecognizer tap = new TapGestureRecognizer(router: router);
bool didStartScale = false; bool didStartScale = false;
ui.Point updatedFocalPoint; Point updatedFocalPoint;
scale.onStart = (ui.Point focalPoint) { scale.onStart = (Point focalPoint) {
didStartScale = true; didStartScale = true;
updatedFocalPoint = focalPoint; updatedFocalPoint = focalPoint;
}; };
double updatedScale; double updatedScale;
scale.onUpdate = (double scale, ui.Point focalPoint) { scale.onUpdate = (double scale, Point focalPoint) {
updatedScale = scale; updatedScale = scale;
updatedFocalPoint = focalPoint; updatedFocalPoint = focalPoint;
}; };
...@@ -35,7 +33,7 @@ void main() { ...@@ -35,7 +33,7 @@ void main() {
TestPointer pointer1 = new TestPointer(1); TestPointer pointer1 = new TestPointer(1);
PointerInputEvent down = pointer1.down(new Point(10.0, 10.0)); PointerDownEvent down = pointer1.down(const Point(10.0, 10.0));
scale.addPointer(down); scale.addPointer(down);
tap.addPointer(down); tap.addPointer(down);
...@@ -54,10 +52,10 @@ void main() { ...@@ -54,10 +52,10 @@ void main() {
expect(didEndScale, isFalse); expect(didEndScale, isFalse);
expect(didTap, isFalse); expect(didTap, isFalse);
router.route(pointer1.move(new Point(20.0, 30.0))); router.route(pointer1.move(const Point(20.0, 30.0)));
expect(didStartScale, isTrue); expect(didStartScale, isTrue);
didStartScale = false; didStartScale = false;
expect(updatedFocalPoint, new ui.Point(20.0, 30.0)); expect(updatedFocalPoint, const Point(20.0, 30.0));
updatedFocalPoint = null; updatedFocalPoint = null;
expect(updatedScale, 1.0); expect(updatedScale, 1.0);
updatedScale = null; updatedScale = null;
...@@ -66,7 +64,7 @@ void main() { ...@@ -66,7 +64,7 @@ void main() {
// Two-finger scaling // Two-finger scaling
TestPointer pointer2 = new TestPointer(2); TestPointer pointer2 = new TestPointer(2);
PointerInputEvent down2 = pointer2.down(new Point(10.0, 20.0)); PointerDownEvent down2 = pointer2.down(const Point(10.0, 20.0));
scale.addPointer(down2); scale.addPointer(down2);
tap.addPointer(down2); tap.addPointer(down2);
GestureArena.instance.close(2); GestureArena.instance.close(2);
...@@ -79,10 +77,10 @@ void main() { ...@@ -79,10 +77,10 @@ void main() {
expect(didStartScale, isFalse); expect(didStartScale, isFalse);
// Zoom in // Zoom in
router.route(pointer2.move(new Point(0.0, 10.0))); router.route(pointer2.move(const Point(0.0, 10.0)));
expect(didStartScale, isTrue); expect(didStartScale, isTrue);
didStartScale = false; didStartScale = false;
expect(updatedFocalPoint, new ui.Point(10.0, 20.0)); expect(updatedFocalPoint, const Point(10.0, 20.0));
updatedFocalPoint = null; updatedFocalPoint = null;
expect(updatedScale, 2.0); expect(updatedScale, 2.0);
updatedScale = null; updatedScale = null;
...@@ -90,8 +88,8 @@ void main() { ...@@ -90,8 +88,8 @@ void main() {
expect(didTap, isFalse); expect(didTap, isFalse);
// Zoom out // Zoom out
router.route(pointer2.move(new Point(15.0, 25.0))); router.route(pointer2.move(const Point(15.0, 25.0)));
expect(updatedFocalPoint, new ui.Point(17.5, 27.5)); expect(updatedFocalPoint, const Point(17.5, 27.5));
updatedFocalPoint = null; updatedFocalPoint = null;
expect(updatedScale, 0.5); expect(updatedScale, 0.5);
updatedScale = null; updatedScale = null;
...@@ -99,7 +97,7 @@ void main() { ...@@ -99,7 +97,7 @@ void main() {
// Three-finger scaling // Three-finger scaling
TestPointer pointer3 = new TestPointer(3); TestPointer pointer3 = new TestPointer(3);
PointerInputEvent down3 = pointer3.down(new Point(25.0, 35.0)); PointerDownEvent down3 = pointer3.down(const Point(25.0, 35.0));
scale.addPointer(down3); scale.addPointer(down3);
tap.addPointer(down3); tap.addPointer(down3);
GestureArena.instance.close(3); GestureArena.instance.close(3);
...@@ -112,10 +110,10 @@ void main() { ...@@ -112,10 +110,10 @@ void main() {
expect(didStartScale, isFalse); expect(didStartScale, isFalse);
// Zoom in // Zoom in
router.route(pointer3.move(new Point(55.0, 65.0))); router.route(pointer3.move(const Point(55.0, 65.0)));
expect(didStartScale, isTrue); expect(didStartScale, isTrue);
didStartScale = false; didStartScale = false;
expect(updatedFocalPoint, new ui.Point(30.0, 40.0)); expect(updatedFocalPoint, const Point(30.0, 40.0));
updatedFocalPoint = null; updatedFocalPoint = null;
expect(updatedScale, 5.0); expect(updatedScale, 5.0);
updatedScale = null; updatedScale = null;
...@@ -123,11 +121,11 @@ void main() { ...@@ -123,11 +121,11 @@ void main() {
expect(didTap, isFalse); expect(didTap, isFalse);
// Return to original positions but with different fingers // Return to original positions but with different fingers
router.route(pointer1.move(new Point(25.0, 35.0))); router.route(pointer1.move(const Point(25.0, 35.0)));
router.route(pointer2.move(new Point(20.0, 30.0))); router.route(pointer2.move(const Point(20.0, 30.0)));
router.route(pointer3.move(new Point(15.0, 25.0))); router.route(pointer3.move(const Point(15.0, 25.0)));
expect(didStartScale, isFalse); expect(didStartScale, isFalse);
expect(updatedFocalPoint, new ui.Point(20.0, 30.0)); expect(updatedFocalPoint, const Point(20.0, 30.0));
updatedFocalPoint = null; updatedFocalPoint = null;
expect(updatedScale, 1.0); expect(updatedScale, 1.0);
updatedScale = null; updatedScale = null;
...@@ -143,10 +141,10 @@ void main() { ...@@ -143,10 +141,10 @@ void main() {
expect(didTap, isFalse); expect(didTap, isFalse);
// Continue scaling with two fingers // Continue scaling with two fingers
router.route(pointer3.move(new Point(10.0, 20.0))); router.route(pointer3.move(const Point(10.0, 20.0)));
expect(didStartScale, isTrue); expect(didStartScale, isTrue);
didStartScale = false; didStartScale = false;
expect(updatedFocalPoint, new ui.Point(15.0, 25.0)); expect(updatedFocalPoint, const Point(15.0, 25.0));
updatedFocalPoint = null; updatedFocalPoint = null;
expect(updatedScale, 2.0); expect(updatedScale, 2.0);
updatedScale = null; updatedScale = null;
...@@ -160,10 +158,10 @@ void main() { ...@@ -160,10 +158,10 @@ void main() {
expect(didTap, isFalse); expect(didTap, isFalse);
// Continue panning with one finger // Continue panning with one finger
router.route(pointer3.move(new Point(0.0, 0.0))); router.route(pointer3.move(const Point(0.0, 0.0)));
expect(didStartScale, isTrue); expect(didStartScale, isTrue);
didStartScale = false; didStartScale = false;
expect(updatedFocalPoint, new ui.Point(0.0, 0.0)); expect(updatedFocalPoint, const Point(0.0, 0.0));
updatedFocalPoint = null; updatedFocalPoint = null;
expect(updatedScale, 1.0); expect(updatedScale, 1.0);
updatedScale = null; updatedScale = null;
......
import 'dart:ui' as ui;
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
...@@ -15,13 +13,13 @@ void main() { ...@@ -15,13 +13,13 @@ void main() {
didStartPan = true; didStartPan = true;
}; };
ui.Offset updatedScrollDelta; Offset updatedScrollDelta;
pan.onUpdate = (ui.Offset offset) { pan.onUpdate = (Offset offset) {
updatedScrollDelta = offset; updatedScrollDelta = offset;
}; };
bool didEndPan = false; bool didEndPan = false;
pan.onEnd = (ui.Offset velocity) { pan.onEnd = (Offset velocity) {
didEndPan = true; didEndPan = true;
}; };
...@@ -31,7 +29,7 @@ void main() { ...@@ -31,7 +29,7 @@ void main() {
}; };
TestPointer pointer = new TestPointer(5); TestPointer pointer = new TestPointer(5);
PointerInputEvent down = pointer.down(new Point(10.0, 10.0)); PointerDownEvent down = pointer.down(const Point(10.0, 10.0));
pan.addPointer(down); pan.addPointer(down);
tap.addPointer(down); tap.addPointer(down);
GestureArena.instance.close(5); GestureArena.instance.close(5);
...@@ -46,17 +44,17 @@ void main() { ...@@ -46,17 +44,17 @@ void main() {
expect(didEndPan, isFalse); expect(didEndPan, isFalse);
expect(didTap, isFalse); expect(didTap, isFalse);
router.route(pointer.move(new Point(20.0, 20.0))); router.route(pointer.move(const Point(20.0, 20.0)));
expect(didStartPan, isTrue); expect(didStartPan, isTrue);
didStartPan = false; didStartPan = false;
expect(updatedScrollDelta, new ui.Offset(10.0, 10.0)); expect(updatedScrollDelta, const Offset(10.0, 10.0));
updatedScrollDelta = null; updatedScrollDelta = null;
expect(didEndPan, isFalse); expect(didEndPan, isFalse);
expect(didTap, isFalse); expect(didTap, isFalse);
router.route(pointer.move(new Point(20.0, 25.0))); router.route(pointer.move(const Point(20.0, 25.0)));
expect(didStartPan, isFalse); expect(didStartPan, isFalse);
expect(updatedScrollDelta, new ui.Offset(0.0, 5.0)); expect(updatedScrollDelta, const Offset(0.0, 5.0));
updatedScrollDelta = null; updatedScrollDelta = null;
expect(didEndPan, isFalse); expect(didEndPan, isFalse);
expect(didTap, isFalse); expect(didTap, isFalse);
......
...@@ -10,55 +10,41 @@ class TestGestureArenaMember extends GestureArenaMember { ...@@ -10,55 +10,41 @@ class TestGestureArenaMember extends GestureArenaMember {
void main() { void main() {
// Down/up pair 1: normal tap sequence // Down/up pair 1: normal tap sequence
final PointerInputEvent down1 = new PointerInputEvent( const PointerDownEvent down1 = const PointerDownEvent(
pointer: 1, pointer: 1,
type: 'pointerdown', position: const Point(10.0, 10.0)
x: 10.0,
y: 10.0
); );
final PointerInputEvent up1 = new PointerInputEvent( const PointerUpEvent up1 = const PointerUpEvent(
pointer: 1, pointer: 1,
type: 'pointerup', position: const Point(11.0, 9.0)
x: 11.0,
y: 9.0
); );
// Down/up pair 2: normal tap sequence far away from pair 1 // Down/up pair 2: normal tap sequence far away from pair 1
final PointerInputEvent down2 = new PointerInputEvent( const PointerDownEvent down2 = const PointerDownEvent(
pointer: 2, pointer: 2,
type: 'pointerdown', position: const Point(30.0, 30.0)
x: 30.0,
y: 30.0
); );
final PointerInputEvent up2 = new PointerInputEvent( const PointerUpEvent up2 = const PointerUpEvent(
pointer: 2, pointer: 2,
type: 'pointerup', position: const Point(31.0, 29.0)
x: 31.0,
y: 29.0
); );
// Down/move/up sequence 3: intervening motion // Down/move/up sequence 3: intervening motion
final PointerInputEvent down3 = new PointerInputEvent( const PointerDownEvent down3 = const PointerDownEvent(
pointer: 3, pointer: 3,
type: 'pointerdown', position: const Point(10.0, 10.0)
x: 10.0,
y: 10.0
); );
final PointerInputEvent move3 = new PointerInputEvent( const PointerMoveEvent move3 = const PointerMoveEvent(
pointer: 3, pointer: 3,
type: 'pointermove', position: const Point(25.0, 25.0)
x: 25.0,
y: 25.0
); );
final PointerInputEvent up3 = new PointerInputEvent( const PointerUpEvent up3 = const PointerUpEvent(
pointer: 3, pointer: 3,
type: 'pointerup', position: const Point(25.0, 25.0)
x: 25.0,
y: 25.0
); );
test('Should recognize tap', () { test('Should recognize tap', () {
......
...@@ -8,56 +8,38 @@ bool _withinTolerance(double actual, double expected) { ...@@ -8,56 +8,38 @@ bool _withinTolerance(double actual, double expected) {
return diff.abs() < kTolerance; return diff.abs() < kTolerance;
} }
bool _checkVelocity(GestureVelocity actual, GestureVelocity expected) { bool _checkVelocity(Offset actual, Offset expected) {
return (actual.isValid == expected.isValid) && return (actual != null)
_withinTolerance(actual.x, expected.x) && && _withinTolerance(actual.dx, expected.dx)
_withinTolerance(actual.y, expected.y); && _withinTolerance(actual.dy, expected.dy);
}
List<PointerInputEvent> _eventFromMap(List<Map> intermediate) {
List<PointerInputEvent> events = new List<PointerInputEvent>();
for (Map entry in intermediate)
events.add(_eventFor(entry));
return events;
}
PointerInputEvent _eventFor(Map entry) {
PointerInputEvent result = new PointerInputEvent(
type: entry['type'],
timeStamp: new Duration(milliseconds: entry['timeStamp'].round()),
pointer: entry['pointer'],
x: entry['x'],
y: entry['y']
);
return result;
} }
void main() { void main() {
List<PointerInputEvent> events = _eventFromMap(velocityEventData); List<Offset> expected = const <Offset>[
const Offset(219.5762939453125, 1304.6705322265625),
List<GestureVelocity> expected = new List<GestureVelocity>(13); const Offset(355.6900939941406, 967.1700439453125),
expected[0] = new GestureVelocity(isValid: true, x: 219.5762939453125, y: 1304.6705322265625); const Offset(12.651158332824707, -36.9227180480957),
expected[1] = new GestureVelocity(isValid: true, x: 355.6900939941406, y: 967.1700439453125); const Offset(714.1383056640625, -2561.540283203125),
expected[2] = new GestureVelocity(isValid: true, x: 12.651158332824707, y: -36.9227180480957); const Offset(-19.658065795898438, -2910.080322265625),
expected[3] = new GestureVelocity(isValid: true, x: 714.1383056640625, y: -2561.540283203125); const Offset(646.8700561523438, 2976.982421875),
expected[4] = new GestureVelocity(isValid: true, x: -19.658065795898438, y: -2910.080322265625); const Offset(396.6878967285156, 2106.204833984375),
expected[5] = new GestureVelocity(isValid: true, x: 646.8700561523438, y: 2976.982421875); const Offset(298.3150634765625, -3660.821044921875),
expected[6] = new GestureVelocity(isValid: true, x: 396.6878967285156, y: 2106.204833984375); const Offset(-1.7460877895355225, -3288.16162109375),
expected[7] = new GestureVelocity(isValid: true, x: 298.3150634765625, y: -3660.821044921875); const Offset(384.6415710449219, -2645.6484375),
expected[8] = new GestureVelocity(isValid: true, x: -1.7460877895355225, y: -3288.16162109375); const Offset(176.3752899169922, 2711.24609375),
expected[9] = new GestureVelocity(isValid: true, x: 384.6415710449219, y: -2645.6484375); const Offset(396.9254455566406, 4280.640625),
expected[10] = new GestureVelocity(isValid: true, x: 176.3752899169922, y: 2711.24609375); const Offset(-71.51288604736328, 3716.74560546875),
expected[11] = new GestureVelocity(isValid: true, x: 396.9254455566406, y: 4280.640625); ];
expected[12] = new GestureVelocity(isValid: true, x: -71.51288604736328, y: 3716.74560546875);
test('Velocity tracker gives expected results', () { test('Velocity tracker gives expected results', () {
VelocityTracker tracker = new VelocityTracker(); VelocityTracker tracker = new VelocityTracker();
int i = 0; int i = 0;
for (PointerInputEvent event in events) { for (PointerEvent event in velocityEventData) {
if (event.type == 'pointerdown' || event.type == 'pointermove') if (event is PointerDownEvent || event is PointerMoveEvent)
tracker.addPosition(event.timeStamp, event.x, event.y); tracker.addPosition(event.timeStamp, event.position);
if (event.type == 'pointerup') { if (event is PointerUpEvent) {
_checkVelocity(tracker.getVelocity(), expected[i++]); _checkVelocity(tracker.getVelocity(), expected[i]);
i += 1;
} }
} }
}); });
......
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