mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
133 lines
4.3 KiB
Dart
133 lines
4.3 KiB
Dart
// 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 'dart:sky' as sky;
|
|
|
|
import 'package:sky/gestures/arena.dart';
|
|
import 'package:sky/gestures/recognizer.dart';
|
|
import 'package:sky/gestures/constants.dart';
|
|
|
|
enum DragState {
|
|
ready,
|
|
possible,
|
|
accepted
|
|
}
|
|
|
|
typedef void GestureDragStartCallback();
|
|
typedef void GestureDragUpdateCallback(double scrollDelta);
|
|
typedef void GestureDragEndCallback();
|
|
|
|
typedef void GesturePanStartCallback();
|
|
typedef void GesturePanUpdateCallback(sky.Offset scrollDelta);
|
|
typedef void GesturePanEndCallback();
|
|
|
|
typedef void _GesturePolymorphicUpdateCallback<T>(T scrollDelta);
|
|
|
|
abstract class _DragGestureRecognizer<T extends dynamic> extends GestureRecognizer {
|
|
_DragGestureRecognizer({ PointerRouter router, this.onStart, this.onUpdate, this.onEnd })
|
|
: super(router: router);
|
|
|
|
GestureDragStartCallback onStart;
|
|
_GesturePolymorphicUpdateCallback<T> onUpdate;
|
|
GestureDragEndCallback onEnd;
|
|
|
|
DragState _state = DragState.ready;
|
|
T _pendingDragDelta;
|
|
|
|
T get _initialPendingDragDelta;
|
|
T _getDragDelta(sky.PointerEvent event);
|
|
bool get _hasSufficientPendingDragDeltaToAccept;
|
|
|
|
void addPointer(sky.PointerEvent event) {
|
|
startTrackingPointer(event.pointer);
|
|
if (_state == DragState.ready) {
|
|
_state = DragState.possible;
|
|
_pendingDragDelta = _initialPendingDragDelta;
|
|
}
|
|
}
|
|
|
|
void handleEvent(sky.PointerEvent event) {
|
|
assert(_state != DragState.ready);
|
|
if (event.type == 'pointermove') {
|
|
T delta = _getDragDelta(event);
|
|
if (_state == DragState.accepted) {
|
|
if (onUpdate != null)
|
|
onUpdate(delta);
|
|
} else {
|
|
_pendingDragDelta += delta;
|
|
if (_hasSufficientPendingDragDeltaToAccept)
|
|
resolve(GestureDisposition.accepted);
|
|
}
|
|
}
|
|
stopTrackingIfPointerNoLongerDown(event);
|
|
}
|
|
|
|
void acceptGesture(int pointer) {
|
|
if (_state != DragState.accepted) {
|
|
_state = DragState.accepted;
|
|
T delta = _pendingDragDelta;
|
|
_pendingDragDelta = null;
|
|
if (onStart != null)
|
|
onStart();
|
|
if (delta != _initialPendingDragDelta && onUpdate != null)
|
|
onUpdate(delta);
|
|
}
|
|
}
|
|
|
|
void didStopTrackingLastPointer() {
|
|
if (_state == DragState.possible) {
|
|
resolve(GestureDisposition.rejected);
|
|
_state = DragState.ready;
|
|
return;
|
|
}
|
|
bool wasAccepted = (_state == DragState.accepted);
|
|
_state = DragState.ready;
|
|
if (wasAccepted && onEnd != null)
|
|
onEnd();
|
|
}
|
|
}
|
|
|
|
class VerticalDragGestureRecognizer extends _DragGestureRecognizer<double> {
|
|
VerticalDragGestureRecognizer({
|
|
PointerRouter router,
|
|
GestureDragStartCallback onStart,
|
|
GestureDragUpdateCallback onUpdate,
|
|
GestureDragEndCallback onEnd
|
|
}) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd);
|
|
|
|
double get _initialPendingDragDelta => 0.0;
|
|
// Notice that we negate dy because scroll offsets go in the opposite direction.
|
|
double _getDragDelta(sky.PointerEvent event) => -event.dy;
|
|
bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop;
|
|
}
|
|
|
|
class HorizontalDragGestureRecognizer extends _DragGestureRecognizer<double> {
|
|
HorizontalDragGestureRecognizer({
|
|
PointerRouter router,
|
|
GestureDragStartCallback onStart,
|
|
GestureDragUpdateCallback onUpdate,
|
|
GestureDragEndCallback onEnd
|
|
}) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd);
|
|
|
|
double get _initialPendingDragDelta => 0.0;
|
|
double _getDragDelta(sky.PointerEvent event) => -event.dx;
|
|
bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop;
|
|
}
|
|
|
|
class PanGestureRecognizer extends _DragGestureRecognizer<sky.Offset> {
|
|
PanGestureRecognizer({
|
|
PointerRouter router,
|
|
GesturePanStartCallback onStart,
|
|
GesturePanUpdateCallback onUpdate,
|
|
GesturePanEndCallback onEnd
|
|
}) : super(router: router, onStart: onStart, onUpdate: onUpdate, onEnd: onEnd);
|
|
|
|
sky.Offset get _initialPendingDragDelta => sky.Offset.zero;
|
|
// Notice that we negate dy because scroll offsets go in the opposite direction.
|
|
sky.Offset _getDragDelta(sky.PointerEvent event) => new sky.Offset(event.dx, -event.dy);
|
|
bool get _hasSufficientPendingDragDeltaToAccept {
|
|
return _pendingDragDelta.dx.abs() > kTouchSlop || _pendingDragDelta.dy.abs() > kTouchSlop;
|
|
}
|
|
}
|