Commit 0e8e8bbb authored by Adam Barth's avatar Adam Barth

Finish dartdoc for gestures.dart (#3994)

parent 83394278
...@@ -63,10 +63,22 @@ bool _isFlingGesture(Velocity velocity) { ...@@ -63,10 +63,22 @@ bool _isFlingGesture(Velocity velocity) {
} }
abstract class _DragGestureRecognizer<T extends dynamic> extends OneSequenceGestureRecognizer { abstract class _DragGestureRecognizer<T extends dynamic> extends OneSequenceGestureRecognizer {
/// A pointer has contacted the screen and might begin to move.
GestureDragDownCallback onDown; GestureDragDownCallback onDown;
/// A pointer has contacted the screen and has begun to move.
GestureDragStartCallback onStart; GestureDragStartCallback onStart;
/// A pointer that is in contact with the screen and moving has moved again.
_GesturePolymorphicUpdateCallback<T> onUpdate; _GesturePolymorphicUpdateCallback<T> onUpdate;
/// A pointer that was previously in contact with the screen and moving is no
/// longer in contact with the screen and was moving at a specific velocity
/// when it stopped contacting the screen.
GestureDragEndCallback onEnd; GestureDragEndCallback onEnd;
/// Signature for when the pointer that previously triggered [onDown] did not
/// complete.
GestureDragCancelCallback onCancel; GestureDragCancelCallback onCancel;
_DragState _state = _DragState.ready; _DragState _state = _DragState.ready;
...@@ -168,6 +180,10 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends OneSequenceGest ...@@ -168,6 +180,10 @@ abstract class _DragGestureRecognizer<T extends dynamic> extends OneSequenceGest
/// Recognizes movement in the vertical direction. /// Recognizes movement in the vertical direction.
/// ///
/// Used for vertical scrolling. /// Used for vertical scrolling.
///
/// See also:
///
/// * [VerticalMultiDragGestureRecognizer]
class VerticalDragGestureRecognizer extends _DragGestureRecognizer<double> { class VerticalDragGestureRecognizer extends _DragGestureRecognizer<double> {
@override @override
double get _initialPendingDragDelta => 0.0; double get _initialPendingDragDelta => 0.0;
...@@ -185,6 +201,10 @@ class VerticalDragGestureRecognizer extends _DragGestureRecognizer<double> { ...@@ -185,6 +201,10 @@ class VerticalDragGestureRecognizer extends _DragGestureRecognizer<double> {
/// Recognizes movement in the horizontal direction. /// Recognizes movement in the horizontal direction.
/// ///
/// Used for horizontal scrolling. /// Used for horizontal scrolling.
///
/// See also:
///
/// * [HorizontalMultiDragGestureRecognizer]
class HorizontalDragGestureRecognizer extends _DragGestureRecognizer<double> { class HorizontalDragGestureRecognizer extends _DragGestureRecognizer<double> {
@override @override
double get _initialPendingDragDelta => 0.0; double get _initialPendingDragDelta => 0.0;
...@@ -200,6 +220,11 @@ class HorizontalDragGestureRecognizer extends _DragGestureRecognizer<double> { ...@@ -200,6 +220,11 @@ class HorizontalDragGestureRecognizer extends _DragGestureRecognizer<double> {
} }
/// Recognizes movement both horizontally and vertically. /// Recognizes movement both horizontally and vertically.
///
/// See also:
///
/// * [ImmediateMultiDragGestureRecognizer]
/// * [DelayedMultiDragGestureRecognizer]
class PanGestureRecognizer extends _DragGestureRecognizer<Offset> { class PanGestureRecognizer extends _DragGestureRecognizer<Offset> {
@override @override
Offset get _initialPendingDragDelta => Offset.zero; Offset get _initialPendingDragDelta => Offset.zero;
......
...@@ -12,22 +12,49 @@ import 'events.dart'; ...@@ -12,22 +12,49 @@ import 'events.dart';
import 'recognizer.dart'; import 'recognizer.dart';
import 'velocity_tracker.dart'; import 'velocity_tracker.dart';
/// Signature for when [MultiDragGestureRecognizer] recognizes the start of a drag gesture.
typedef Drag GestureMultiDragStartCallback(Point position); typedef Drag GestureMultiDragStartCallback(Point position);
class Drag { /// Interface for receiving updates about drags from a [MultiDragGestureRecognizer].
abstract class Drag {
/// The pointer has moved by the given offset.
void move(Offset offset) { } void move(Offset offset) { }
/// The pointer is no longer in contact with the screen and was moving at a
/// given velocity when it stopped contacting the screen.
void end(Velocity velocity) { } void end(Velocity velocity) { }
/// The input from the pointer is no longer directed towards this receiver.
///
/// For example, the user might have been interrupted by a system-modal dialog
/// in the middle of the drag.
void cancel() { } void cancel() { }
} }
/// Per-pointer state for a [MultiDragGestureRecognizer].
///
/// A [MultiDragGestureRecognizer] tracks each pointer separately. The state for
/// each pointer is a subclass of [MultiDragPointerState].
abstract class MultiDragPointerState { abstract class MultiDragPointerState {
MultiDragPointerState(this.initialPosition); /// Creates per-pointer state for a [MultiDragGestureRecognizer].
///
/// The [initialPosition] argument must not be null.
MultiDragPointerState(this.initialPosition) {
assert(initialPosition != null);
}
/// The global coordinates of the pointer when the pointer contacted the screen.
final Point initialPosition; final Point initialPosition;
final VelocityTracker _velocityTracker = new VelocityTracker(); final VelocityTracker _velocityTracker = new VelocityTracker();
Drag _client; Drag _client;
/// The offset of the pointer from the last position that was reported to the client.
///
/// After the pointer contacts the screen, the pointer might move some
/// distance before this movement will be recognized as a drag. This field
/// accumulates that movement so that we can report it to the client after
/// the drag starts.
Offset get pendingDelta => _pendingDelta; Offset get pendingDelta => _pendingDelta;
Offset _pendingDelta = Offset.zero; Offset _pendingDelta = Offset.zero;
...@@ -39,6 +66,7 @@ abstract class MultiDragPointerState { ...@@ -39,6 +66,7 @@ abstract class MultiDragPointerState {
_arenaEntry = entry; _arenaEntry = entry;
} }
/// Resolve this pointer's entry in the [GestureArenaManager] with the given disposition.
void resolve(GestureDisposition disposition) { void resolve(GestureDisposition disposition) {
_arenaEntry.resolve(disposition); _arenaEntry.resolve(disposition);
} }
...@@ -115,12 +143,35 @@ abstract class MultiDragPointerState { ...@@ -115,12 +143,35 @@ abstract class MultiDragPointerState {
_arenaEntry = null; _arenaEntry = null;
} }
/// Releases any resources used by the object.
void dispose() { void dispose() {
assert(() { _pendingDelta = null; return true; }); assert(() { _pendingDelta = null; return true; });
} }
} }
/// Recognizes movement on a per-pointer basis.
///
/// In contrast to [HorizontalDragGestureRecognizer],
/// [VerticalDragGestureRecognizer], and [PanGestureRecognizer],
/// [MultiDragGestureRecognizer] watches each pointer separately, which means
/// multiple drags can be recognized concurrently if multiple pointers are in
/// contact with the screen.
///
/// [MultiDragGestureRecognizer] is not intended to be used directly. Instead,
/// consider using one of its subclasses to recognize specific types for drag
/// gestures.
///
/// See also:
///
/// * [HorizontalMultiDragGestureRecognizer]
/// * [VerticalMultiDragGestureRecognizer]
/// * [ImmediateMultiDragGestureRecognizer]
/// * [DelayedMultiDragGestureRecognizer]
abstract class MultiDragGestureRecognizer<T extends MultiDragPointerState> extends GestureRecognizer { abstract class MultiDragGestureRecognizer<T extends MultiDragPointerState> extends GestureRecognizer {
/// Called when this class recognizes the start of a drag gesture.
///
/// The remaining notifications for this drag gesture are delivered to the
/// [Drag] object returned by this callback.
GestureMultiDragStartCallback onStart; GestureMultiDragStartCallback onStart;
Map<int, T> _pointers = <int, T>{}; Map<int, T> _pointers = <int, T>{};
...@@ -133,13 +184,15 @@ abstract class MultiDragGestureRecognizer<T extends MultiDragPointerState> exten ...@@ -133,13 +184,15 @@ abstract class MultiDragGestureRecognizer<T extends MultiDragPointerState> exten
assert(!_pointers.containsKey(event.pointer)); assert(!_pointers.containsKey(event.pointer));
T state = createNewPointerState(event); T state = createNewPointerState(event);
_pointers[event.pointer] = state; _pointers[event.pointer] = state;
GestureBinding.instance.pointerRouter.addRoute(event.pointer, handleEvent); GestureBinding.instance.pointerRouter.addRoute(event.pointer, _handleEvent);
state._setArenaEntry(GestureBinding.instance.gestureArena.add(event.pointer, this)); state._setArenaEntry(GestureBinding.instance.gestureArena.add(event.pointer, this));
} }
/// Subclasses should override this function to create per-pointer state
/// objects to track the pointer associated with the given event.
T createNewPointerState(PointerDownEvent event); T createNewPointerState(PointerDownEvent event);
void handleEvent(PointerEvent event) { void _handleEvent(PointerEvent event) {
assert(_pointers != null); assert(_pointers != null);
assert(event.pointer != null); assert(event.pointer != null);
assert(event.timeStamp != null); assert(event.timeStamp != null);
...@@ -203,7 +256,7 @@ abstract class MultiDragGestureRecognizer<T extends MultiDragPointerState> exten ...@@ -203,7 +256,7 @@ abstract class MultiDragGestureRecognizer<T extends MultiDragPointerState> exten
void _removeState(int pointer) { void _removeState(int pointer) {
assert(_pointers != null); assert(_pointers != null);
assert(_pointers.containsKey(pointer)); assert(_pointers.containsKey(pointer));
GestureBinding.instance.pointerRouter.removeRoute(pointer, handleEvent); GestureBinding.instance.pointerRouter.removeRoute(pointer, _handleEvent);
_pointers[pointer].dispose(); _pointers[pointer].dispose();
_pointers.remove(pointer); _pointers.remove(pointer);
} }
...@@ -215,10 +268,8 @@ abstract class MultiDragGestureRecognizer<T extends MultiDragPointerState> exten ...@@ -215,10 +268,8 @@ abstract class MultiDragGestureRecognizer<T extends MultiDragPointerState> exten
_pointers = null; _pointers = null;
super.dispose(); super.dispose();
} }
} }
class _ImmediatePointerState extends MultiDragPointerState { class _ImmediatePointerState extends MultiDragPointerState {
_ImmediatePointerState(Point initialPosition) : super(initialPosition); _ImmediatePointerState(Point initialPosition) : super(initialPosition);
...@@ -235,6 +286,16 @@ class _ImmediatePointerState extends MultiDragPointerState { ...@@ -235,6 +286,16 @@ class _ImmediatePointerState extends MultiDragPointerState {
} }
} }
/// Recognizes movement both horizontally and vertically on a per-pointer basis.
///
/// In contrast to [PanGestureRecognizer], [ImmediateMultiDragGestureRecognizer]
/// watches each pointer separately, which means multiple drags can be
/// recognized concurrently if multiple pointers are in contact with the screen.
///
/// See also:
///
/// * [PanGestureRecognizer]
/// * [DelayedMultiDragGestureRecognizer]
class ImmediateMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_ImmediatePointerState> { class ImmediateMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_ImmediatePointerState> {
@override @override
_ImmediatePointerState createNewPointerState(PointerDownEvent event) { _ImmediatePointerState createNewPointerState(PointerDownEvent event) {
...@@ -262,6 +323,16 @@ class _HorizontalPointerState extends MultiDragPointerState { ...@@ -262,6 +323,16 @@ class _HorizontalPointerState extends MultiDragPointerState {
} }
} }
/// Recognizes movement in the horizontal direction on a per-pointer basis.
///
/// In contrast to [HorizontalDragGestureRecognizer],
/// [HorizontalMultiDragGestureRecognizer] watches each pointer separately,
/// which means multiple drags can be recognized concurrently if multiple
/// pointers are in contact with the screen.
///
/// See also:
///
/// * [HorizontalDragGestureRecognizer]
class HorizontalMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_HorizontalPointerState> { class HorizontalMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_HorizontalPointerState> {
@override @override
_HorizontalPointerState createNewPointerState(PointerDownEvent event) { _HorizontalPointerState createNewPointerState(PointerDownEvent event) {
...@@ -289,6 +360,16 @@ class _VerticalPointerState extends MultiDragPointerState { ...@@ -289,6 +360,16 @@ class _VerticalPointerState extends MultiDragPointerState {
} }
} }
/// Recognizes movement in the vertical direction on a per-pointer basis.
///
/// In contrast to [VerticalDragGestureRecognizer],
/// [VerticalMultiDragGestureRecognizer] watches each pointer separately,
/// which means multiple drags can be recognized concurrently if multiple
/// pointers are in contact with the screen.
///
/// See also:
///
/// * [VerticalDragGestureRecognizer]
class VerticalMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_VerticalPointerState> { class VerticalMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_VerticalPointerState> {
@override @override
_VerticalPointerState createNewPointerState(PointerDownEvent event) { _VerticalPointerState createNewPointerState(PointerDownEvent event) {
...@@ -299,7 +380,6 @@ class VerticalMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_Ver ...@@ -299,7 +380,6 @@ class VerticalMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_Ver
String toStringShort() => 'vertical multidrag'; String toStringShort() => 'vertical multidrag';
} }
class _DelayedPointerState extends MultiDragPointerState { class _DelayedPointerState extends MultiDragPointerState {
_DelayedPointerState(Point initialPosition, Duration delay) : super(initialPosition) { _DelayedPointerState(Point initialPosition, Duration delay) : super(initialPosition) {
assert(delay != null); assert(delay != null);
...@@ -348,13 +428,36 @@ class _DelayedPointerState extends MultiDragPointerState { ...@@ -348,13 +428,36 @@ class _DelayedPointerState extends MultiDragPointerState {
} }
} }
/// Recognizes movement both horizontally and vertically on a per-pointer basis after a delay.
///
/// In constrast to [ImmediateMultiDragGestureRecognizer],
/// [DelayedMultiDragGestureRecognizer] waits for a [delay] before recognizing
/// the drag. If the pointer moves more than [kTouchSlop] before the delay
/// expires, the gesture is not recognized.
///
/// In contrast to [PanGestureRecognizer], [DelayedMultiDragGestureRecognizer]
/// watches each pointer separately, which means multiple drags can be
/// recognized concurrently if multiple pointers are in contact with the screen.
///
/// See also:
///
/// * [PanGestureRecognizer]
/// * [ImmediateMultiDragGestureRecognizer]
class DelayedMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_DelayedPointerState> { class DelayedMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_DelayedPointerState> {
/// Creates a drag recognizer that works on a per-pointer basis after a delay.
///
/// In order for a drag to be recognized by this recognizer, the pointer must
/// remain in the same place for [delay] (up to [kTouchSlop]). The [delay]
/// defaults to [kLongPressTimeout] to match [LongPressGestureRecognizer] but
/// can be changed for specific behaviors.
DelayedMultiDragGestureRecognizer({ DelayedMultiDragGestureRecognizer({
Duration delay: kLongPressTimeout Duration delay: kLongPressTimeout
}) : _delay = delay { }) : _delay = delay {
assert(delay != null); assert(delay != null);
} }
/// The amount of time the pointer must remain in the same place for the drag
/// to be recognized.
Duration get delay => _delay; Duration get delay => _delay;
Duration _delay; Duration _delay;
set delay(Duration value) { set delay(Duration value) {
......
...@@ -12,17 +12,28 @@ import 'events.dart'; ...@@ -12,17 +12,28 @@ import 'events.dart';
import 'pointer_router.dart'; import 'pointer_router.dart';
import 'recognizer.dart'; import 'recognizer.dart';
/// Signature for callback when the user has tapped the screen at the same
/// location twice in quick succession.
typedef void GestureDoubleTapCallback(); typedef void GestureDoubleTapCallback();
/// Signature used by [MultiTapGestureRecognizer] for when a pointer that might
/// cause a tap has contacted the screen at a particular location.
typedef void GestureMultiTapDownCallback(Point globalPosition, int pointer); typedef void GestureMultiTapDownCallback(Point globalPosition, int pointer);
/// Signature used by [MultiTapGestureRecognizer] for when a pointer that will
/// trigger a tap has stopped contacting the screen at a particular location.
typedef void GestureMultiTapUpCallback(Point globalPosition, int pointer); typedef void GestureMultiTapUpCallback(Point globalPosition, int pointer);
/// Signature used by [MultiTapGestureRecognizer] for when a tap has occurred.
typedef void GestureMultiTapCallback(int pointer); typedef void GestureMultiTapCallback(int pointer);
/// Signature for when the pointer that previously triggered a
/// [GestureMultiTapDownCallback] will not end up causing a tap.
typedef void GestureMultiTapCancelCallback(int pointer); typedef void GestureMultiTapCancelCallback(int pointer);
/// TapTracker helps track individual tap sequences as part of a /// TapTracker helps track individual tap sequences as part of a
/// larger gesture. /// larger gesture.
class _TapTracker { class _TapTracker {
_TapTracker({ PointerDownEvent event, this.entry }) _TapTracker({ PointerDownEvent event, this.entry })
: pointer = event.pointer, : pointer = event.pointer,
_initialPosition = event.position; _initialPosition = event.position;
...@@ -51,10 +62,10 @@ class _TapTracker { ...@@ -51,10 +62,10 @@ class _TapTracker {
Offset offset = event.position - _initialPosition; Offset offset = event.position - _initialPosition;
return offset.distance <= tolerance; return offset.distance <= tolerance;
} }
} }
/// Recognizes when the user has tapped the screen at the same location twice in
/// quick succession.
class DoubleTapGestureRecognizer extends GestureRecognizer { class DoubleTapGestureRecognizer extends GestureRecognizer {
// Implementation notes: // Implementation notes:
// The double tap recognizer can be in one of four states. There's no // The double tap recognizer can be in one of four states. There's no
...@@ -76,6 +87,8 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { ...@@ -76,6 +87,8 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
// - The long timer between taps expires // - The long timer between taps expires
// - The gesture arena decides we have been rejected wholesale // - The gesture arena decides we have been rejected wholesale
/// Called when the user has tapped the screen at the same location twice in
/// quick succession.
GestureDoubleTapCallback onDoubleTap; GestureDoubleTapCallback onDoubleTap;
Timer _doubleTapTimer; Timer _doubleTapTimer;
...@@ -94,10 +107,10 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { ...@@ -94,10 +107,10 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
entry: GestureBinding.instance.gestureArena.add(event.pointer, this) entry: GestureBinding.instance.gestureArena.add(event.pointer, this)
); );
_trackers[event.pointer] = tracker; _trackers[event.pointer] = tracker;
tracker.startTrackingPointer(handleEvent); tracker.startTrackingPointer(_handleEvent);
} }
void handleEvent(PointerEvent event) { void _handleEvent(PointerEvent event) {
_TapTracker tracker = _trackers[event.pointer]; _TapTracker tracker = _trackers[event.pointer];
assert(tracker != null); assert(tracker != null);
if (event is PointerUpEvent) { if (event is PointerUpEvent) {
...@@ -188,7 +201,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer { ...@@ -188,7 +201,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
} }
void _freezeTracker(_TapTracker tracker) { void _freezeTracker(_TapTracker tracker) {
tracker.stopTrackingPointer(handleEvent); tracker.stopTrackingPointer(_handleEvent);
} }
void _startDoubleTapTimer() { void _startDoubleTapTimer() {
...@@ -293,20 +306,44 @@ class _TapGesture extends _TapTracker { ...@@ -293,20 +306,44 @@ class _TapGesture extends _TapTracker {
} }
/// MultiTapGestureRecognizer is a tap recognizer that treats taps /// Recognizes taps on a per-pointer basis.
/// independently. That is, each pointer sequence that could resolve to a tap ///
/// does so independently of others: down-1, down-2, up-1, up-2 produces two /// [MultiTapGestureRecognizer] considers each sequence of pointer events that
/// taps, on up-1 and up-2. /// could constitute a tap independently of other pointers: For example, down-1,
/// down-2, up-1, up-2 produces two taps, on up-1 and up-2.
///
/// See also:
///
/// * [TapGestureRecognizer]
class MultiTapGestureRecognizer extends GestureRecognizer { class MultiTapGestureRecognizer extends GestureRecognizer {
/// Creates a multi-tap gesture recognizer.
///
/// The [longTapDelay] defaults to [Duration.ZERO], which means
/// [onLongTapDown] is called immediately after [onTapDown].
MultiTapGestureRecognizer({ MultiTapGestureRecognizer({
this.longTapDelay: Duration.ZERO this.longTapDelay: Duration.ZERO
}); });
/// A pointer that might cause a tap has contacted the screen at a particular
/// location.
GestureMultiTapDownCallback onTapDown; GestureMultiTapDownCallback onTapDown;
/// A pointer that will trigger a tap has stopped contacting the screen at a
/// particular location.
GestureMultiTapUpCallback onTapUp; GestureMultiTapUpCallback onTapUp;
/// A tap has occurred.
GestureMultiTapCallback onTap; GestureMultiTapCallback onTap;
/// The pointer that previously triggered [onTapDown] will not end up causing
/// a tap.
GestureMultiTapCancelCallback onTapCancel; GestureMultiTapCancelCallback onTapCancel;
/// The amount of time between [onTapDown] and [onLongTapDown].
Duration longTapDelay; Duration longTapDelay;
/// A pointer that might cause a tap is still in contact with the screen at a
/// particular location after [longTapDelay].
GestureMultiTapDownCallback onLongTapDown; GestureMultiTapDownCallback onLongTapDown;
final Map<int, _TapGesture> _gestureMap = new Map<int, _TapGesture>(); final Map<int, _TapGesture> _gestureMap = new Map<int, _TapGesture>();
......
...@@ -20,7 +20,6 @@ export 'pointer_router.dart' show PointerRouter; ...@@ -20,7 +20,6 @@ export 'pointer_router.dart' show PointerRouter;
/// gesture recognizers but don't care about the specific details of /// gesture recognizers but don't care about the specific details of
/// the gestures recognizers themselves. /// the gestures recognizers themselves.
abstract class GestureRecognizer extends GestureArenaMember { abstract class GestureRecognizer extends GestureArenaMember {
/// Registers a new pointer that might be relevant to this gesture /// Registers a new pointer that might be relevant to this gesture
/// detector. /// detector.
/// ///
...@@ -60,6 +59,7 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -60,6 +59,7 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
final Map<int, GestureArenaEntry> _entries = <int, GestureArenaEntry>{}; final Map<int, GestureArenaEntry> _entries = <int, GestureArenaEntry>{};
final Set<int> _trackedPointers = new HashSet<int>(); final Set<int> _trackedPointers = new HashSet<int>();
/// Called when a pointer event is routed to this recongizer.
void handleEvent(PointerEvent event); void handleEvent(PointerEvent event);
@override @override
...@@ -68,8 +68,13 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -68,8 +68,13 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
@override @override
void rejectGesture(int pointer) { } void rejectGesture(int pointer) { }
/// Called when the number of pointers this recognizers is tracking changes from one to zero.
///
/// The given pointer ID is the ID of the last pointer this recognizer was
/// tracking.
void didStopTrackingLastPointer(int pointer); void didStopTrackingLastPointer(int pointer);
/// Resolves this recognizer's participation in each gesture arena with the given disposition.
void resolve(GestureDisposition disposition) { void resolve(GestureDisposition disposition) {
List<GestureArenaEntry> localEntries = new List<GestureArenaEntry>.from(_entries.values); List<GestureArenaEntry> localEntries = new List<GestureArenaEntry>.from(_entries.values);
_entries.clear(); _entries.clear();
...@@ -86,6 +91,11 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -86,6 +91,11 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
assert(_entries.isEmpty); assert(_entries.isEmpty);
} }
/// Causes events related to the given pointer ID to be routed to this recognizer.
///
/// The pointer events are delivered to [handleEvent].
///
/// Use [stopTrackingPointer] to remove the route added by this function.
void startTrackingPointer(int pointer) { void startTrackingPointer(int pointer) {
GestureBinding.instance.pointerRouter.addRoute(pointer, handleEvent); GestureBinding.instance.pointerRouter.addRoute(pointer, handleEvent);
_trackedPointers.add(pointer); _trackedPointers.add(pointer);
...@@ -93,6 +103,12 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -93,6 +103,12 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
_entries[pointer] = GestureBinding.instance.gestureArena.add(pointer, this); _entries[pointer] = GestureBinding.instance.gestureArena.add(pointer, this);
} }
/// Stops events related to the given pointer ID from being routed to this recognizer.
///
/// If this function reduces the number of tracked pointers to zero, it will
/// call [didStopTrackingLastPointer] synchronously.
///
/// Use [startTrackingPointer] to add the routes in the first place.
void stopTrackingPointer(int pointer) { void stopTrackingPointer(int pointer) {
GestureBinding.instance.pointerRouter.removeRoute(pointer, handleEvent); GestureBinding.instance.pointerRouter.removeRoute(pointer, handleEvent);
_trackedPointers.remove(pointer); _trackedPointers.remove(pointer);
...@@ -100,32 +116,62 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer { ...@@ -100,32 +116,62 @@ abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
didStopTrackingLastPointer(pointer); didStopTrackingLastPointer(pointer);
} }
/// Calls [stopTrackingPointer] if the pointer with the given ID is being tracked by this recognizer.
void ensureNotTrackingPointer(int pointer) { void ensureNotTrackingPointer(int pointer) {
if (_trackedPointers.contains(pointer)) if (_trackedPointers.contains(pointer))
stopTrackingPointer(pointer); stopTrackingPointer(pointer);
} }
/// Stops tracking the pointer associated with the given event if the event is
/// a [PointerUpEvent] or a [PointerCancelEvent] event.
void stopTrackingIfPointerNoLongerDown(PointerEvent event) { void stopTrackingIfPointerNoLongerDown(PointerEvent event) {
if (event is PointerUpEvent || event is PointerCancelEvent) if (event is PointerUpEvent || event is PointerCancelEvent)
stopTrackingPointer(event.pointer); stopTrackingPointer(event.pointer);
} }
} }
/// The possible states of a [PrimaryPointerGestureRecognizer].
///
/// The recognizer advances from [ready] to [possible] when starts tracking a
/// primary pointer. When the primary pointer is resolve (either accepted or
/// or rejected), the recognizers advances to [defunct]. Once the recognizer
/// has stopped tracking any remaining pointers, the recognizer returns to
/// [ready].
enum GestureRecognizerState { enum GestureRecognizerState {
/// The recognizer is ready to start recognizing a gesture.
ready, ready,
/// The sequence of pointer events seen thus far are consistent with the
/// gesture the recognizer is attempting to recognize but the gesture has not
/// been accepted definitively.
possible, possible,
defunct
/// Further pointer events cannot cause this recognizer to recognise the
/// gesture until the recognizer returns to the [ready] state (typically when
/// all the pointers the recognizer is tracking are removed from the screen).
defunct,
} }
/// A base class for gesture recognizers that track a single primary pointer.
abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecognizer { abstract class PrimaryPointerGestureRecognizer extends OneSequenceGestureRecognizer {
/// Initializes the [deadline] field during construction of subclasses.
PrimaryPointerGestureRecognizer({ this.deadline }); PrimaryPointerGestureRecognizer({ this.deadline });
/// If non-null, the recognizer will call [didExceedDeadline] after this
/// amount of time has elapsed since starting to track the primary pointer.
final Duration deadline; final Duration deadline;
/// The current state of the recognizer.
///
/// See [GestureRecognizerState] for a description of the states.
GestureRecognizerState state = GestureRecognizerState.ready; GestureRecognizerState state = GestureRecognizerState.ready;
/// The ID of the primary pointer this recognizer is tracking.
int primaryPointer; int primaryPointer;
/// The global location at which the primary pointer contacted the screen.
Point initialPosition; Point initialPosition;
Timer _timer; Timer _timer;
@override @override
......
...@@ -7,20 +7,53 @@ import 'recognizer.dart'; ...@@ -7,20 +7,53 @@ import 'recognizer.dart';
import 'constants.dart'; import 'constants.dart';
import 'events.dart'; import 'events.dart';
/// The possible states of a [ScaleGestureRecognizer].
enum ScaleState { enum ScaleState {
/// The recognizer is ready to start recognizing a gesture.
ready, ready,
/// The sequence of pointer events seen thus far are consistent with a scale
/// gesture but the gesture has not been accepted definitively.
possible, possible,
/// The sequence of pointer events seen thus far have been accepted
/// definitively as a scale gesture.
accepted, accepted,
started
/// The sequence of pointer events seen thus far have been accepted
/// definitively as a scale gesture and the pointers established a focal point
/// and initial scale.
started,
} }
/// Signature for when the pointers in contact with the screen have begun
/// established a focal point and initial scale of 1.0.
typedef void GestureScaleStartCallback(Point focalPoint); typedef void GestureScaleStartCallback(Point focalPoint);
/// Signature for when the pointers in contact with the screen have indicated a
/// new focal point and/or scale.
typedef void GestureScaleUpdateCallback(double scale, Point focalPoint); typedef void GestureScaleUpdateCallback(double scale, Point focalPoint);
/// Signature for when the pointers are no longer in contact with the screen.
typedef void GestureScaleEndCallback(); typedef void GestureScaleEndCallback();
/// Recognizes a scale gesture.
///
/// [ScaleGestureRecognizer] tracks the pointers in contact with the screen and
/// calculates their focal point and indiciated scale. When a focal pointer is
/// established, the recognizer calls [onStart]. As the focal point and scale
/// change, the recognizer calls [onUpdate]. When the pointers are no longer in
/// contact with the screen, the recognizer calls [onEnd].
class ScaleGestureRecognizer extends OneSequenceGestureRecognizer { class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
/// The pointers in contact with the screen have begun established a focal
/// point and initial scale of 1.0.
GestureScaleStartCallback onStart; GestureScaleStartCallback onStart;
/// The pointers in contact with the screen have indicated a new focal point
/// and/or scale.
GestureScaleUpdateCallback onUpdate; GestureScaleUpdateCallback onUpdate;
/// The pointers are no longer in contact with the screen.
GestureScaleEndCallback onEnd; GestureScaleEndCallback onEnd;
ScaleState _state = ScaleState.ready; ScaleState _state = ScaleState.ready;
......
...@@ -7,20 +7,48 @@ import 'constants.dart'; ...@@ -7,20 +7,48 @@ import 'constants.dart';
import 'events.dart'; import 'events.dart';
import 'recognizer.dart'; import 'recognizer.dart';
/// Signature for when a pointer that might cause a tap has contacted the screen
/// at a particular location.
typedef void GestureTapDownCallback(Point globalPosition); typedef void GestureTapDownCallback(Point globalPosition);
/// Signature for when a pointer that will trigger a tap has stopped contacting
/// the screen at a particular location.
typedef void GestureTapUpCallback(Point globalPosition); typedef void GestureTapUpCallback(Point globalPosition);
/// Signature for when a tap has occurred.
typedef void GestureTapCallback(); typedef void GestureTapCallback();
/// Signature for when the pointer that previously triggered a
/// [GestureTapDownCallback] will not end up causing a tap.
typedef void GestureTapCancelCallback(); typedef void GestureTapCancelCallback();
/// TapGestureRecognizer is a tap recognizer that tracks only one primary /// Recognizes taps.
/// pointer per gesture. That is, during tap recognition, extra pointer events ///
/// are ignored: down-1, down-2, up-1, up-2 produces only one tap on up-1. /// [TapGestureRecognizer] considers all the pointers involved in the pointer
/// event sequence as contributing to one gesture. For this reason, extra
/// pointer interactions during a tap sequence are not recognized as additional
/// taps. Fo example, down-1, down-2, up-1, up-2 produces only one tap on up-1.
///
/// See also:
///
/// * [MultiTapGestureRecognizer]
class TapGestureRecognizer extends PrimaryPointerGestureRecognizer { class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
/// Creates a tap gesture recognizer.
TapGestureRecognizer() : super(deadline: kPressTimeout); TapGestureRecognizer() : super(deadline: kPressTimeout);
/// A pointer that might cause a tap has contacted the screen at a particular
/// location.
GestureTapDownCallback onTapDown; GestureTapDownCallback onTapDown;
/// A pointer that will trigger a tap has stopped contacting the screen at a
/// particular location.
GestureTapUpCallback onTapUp; GestureTapUpCallback onTapUp;
/// A tap has occurred.
GestureTapCallback onTap; GestureTapCallback onTap;
/// The pointer that previously triggered [onTapDown] will not end up causing
/// a tap.
GestureTapCancelCallback onTapCancel; GestureTapCancelCallback onTapCancel;
bool _sentTapDown = false; bool _sentTapDown = false;
......
...@@ -214,6 +214,9 @@ class _LeastSquaresVelocityTrackerStrategy extends _VelocityTrackerStrategy { ...@@ -214,6 +214,9 @@ class _LeastSquaresVelocityTrackerStrategy extends _VelocityTrackerStrategy {
/// A velocity in two dimensions. /// A velocity in two dimensions.
class Velocity { class Velocity {
/// Creates a velocity.
///
/// The [pixelsPerSecond] argument must not be null.
const Velocity({ this.pixelsPerSecond }); const Velocity({ this.pixelsPerSecond });
/// A velocity that isn't moving at all. /// A velocity that isn't moving at all.
...@@ -222,11 +225,16 @@ class Velocity { ...@@ -222,11 +225,16 @@ class Velocity {
/// The number of pixels per second of velocity in the x and y directions. /// The number of pixels per second of velocity in the x and y directions.
final Offset pixelsPerSecond; final Offset pixelsPerSecond;
/// Return the negation of a velocity.
Velocity operator -() => new Velocity(pixelsPerSecond: -pixelsPerSecond); Velocity operator -() => new Velocity(pixelsPerSecond: -pixelsPerSecond);
/// Return the difference of two velocities.
Velocity operator -(Velocity other) { Velocity operator -(Velocity other) {
return new Velocity( return new Velocity(
pixelsPerSecond: pixelsPerSecond - other.pixelsPerSecond); pixelsPerSecond: pixelsPerSecond - other.pixelsPerSecond);
} }
/// Return the sum of two velocities.
Velocity operator +(Velocity other) { Velocity operator +(Velocity other) {
return new Velocity( return new Velocity(
pixelsPerSecond: pixelsPerSecond + other.pixelsPerSecond); pixelsPerSecond: pixelsPerSecond + other.pixelsPerSecond);
...@@ -264,6 +272,7 @@ class VelocityTracker { ...@@ -264,6 +272,7 @@ class VelocityTracker {
/// before assuming the pointer stopped. /// before assuming the pointer stopped.
static const Duration kAssumePointerMoveStoppedTime = const Duration(milliseconds: 40); static const Duration kAssumePointerMoveStoppedTime = const Duration(milliseconds: 40);
/// Creates a velocity tracker.
VelocityTracker() : _strategy = _createStrategy(); VelocityTracker() : _strategy = _createStrategy();
Duration _lastTimeStamp = const Duration(); Duration _lastTimeStamp = const Duration();
......
...@@ -178,8 +178,15 @@ class GestureDetector extends StatelessWidget { ...@@ -178,8 +178,15 @@ class GestureDetector extends StatelessWidget {
/// The pointer that previously triggered [onPanDown] did not complete. /// The pointer that previously triggered [onPanDown] did not complete.
final GesturePanCancelCallback onPanCancel; final GesturePanCancelCallback onPanCancel;
/// The pointers in contact with the screen have begun established a focal
/// point and initial scale of 1.0.
final GestureScaleStartCallback onScaleStart; final GestureScaleStartCallback onScaleStart;
/// The pointers in contact with the screen have indicated a new focal point
/// and/or scale.
final GestureScaleUpdateCallback onScaleUpdate; final GestureScaleUpdateCallback onScaleUpdate;
/// The pointers are no longer in contact with the screen.
final GestureScaleEndCallback onScaleEnd; final GestureScaleEndCallback onScaleEnd;
/// How this gesture detector should behave during hit testing. /// How this gesture detector should behave during hit testing.
......
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