Commit 941d69db authored by Ian Hickson's avatar Ian Hickson

Merge pull request #2140 from Hixie/mutable-gesture-detector

Just-in-time mutations of GestureDetector
parents d1154c25 0df3730d
......@@ -6,6 +6,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.flutter.MaterialGallery" android:versionCode="1" android:versionName="0.0.1">
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET"/>
<application android:icon="@mipmap/ic_launcher" android:label="Flutter Material" android:name="org.domokit.sky.shell.SkyApplication">
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize" android:hardwareAccelerated="true" android:launchMode="singleTask" android:name="org.domokit.sky.shell.SkyActivity" android:theme="@android:style/Theme.Black.NoTitleBar">
......
......@@ -143,6 +143,8 @@ class VerticalDragGestureRecognizer extends _DragGestureRecognizer<double> {
double get _initialPendingDragDelta => 0.0;
double _getDragDelta(PointerEvent event) => event.delta.dy;
bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop;
String toStringShort() => 'vertical drag';
}
class HorizontalDragGestureRecognizer extends _DragGestureRecognizer<double> {
......@@ -163,6 +165,8 @@ class HorizontalDragGestureRecognizer extends _DragGestureRecognizer<double> {
double get _initialPendingDragDelta => 0.0;
double _getDragDelta(PointerEvent event) => event.delta.dx;
bool get _hasSufficientPendingDragDeltaToAccept => _pendingDragDelta.abs() > kTouchSlop;
String toStringShort() => 'horizontal drag';
}
class PanGestureRecognizer extends _DragGestureRecognizer<Offset> {
......@@ -185,4 +189,6 @@ class PanGestureRecognizer extends _DragGestureRecognizer<Offset> {
bool get _hasSufficientPendingDragDeltaToAccept {
return _pendingDragDelta.distance > kPanSlop;
}
String toStringShort() => 'pan';
}
......@@ -34,4 +34,6 @@ class LongPressGestureRecognizer extends PrimaryPointerGestureRecognizer {
if (event is PointerUpEvent)
resolve(GestureDisposition.rejected);
}
String toStringShort() => 'long press';
}
......@@ -250,6 +250,8 @@ class ImmediateMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_Im
_ImmediatePointerState createNewPointerState(PointerDownEvent event) {
return new _ImmediatePointerState(event.position);
}
String toStringShort() => 'multidrag';
}
......@@ -277,6 +279,8 @@ class HorizontalMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_H
_HorizontalPointerState createNewPointerState(PointerDownEvent event) {
return new _HorizontalPointerState(event.position);
}
String toStringShort() => 'horizontal multidrag';
}
......@@ -304,6 +308,8 @@ class VerticalMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_Ver
_VerticalPointerState createNewPointerState(PointerDownEvent event) {
return new _VerticalPointerState(event.position);
}
String toStringShort() => 'vertical multidrag';
}
......@@ -373,4 +379,6 @@ class DelayedMultiDragGestureRecognizer extends MultiDragGestureRecognizer<_Dela
_DelayedPointerState createNewPointerState(PointerDownEvent event) {
return new _DelayedPointerState(event.position, _delay);
}
String toStringShort() => 'long multidrag';
}
......@@ -212,6 +212,7 @@ class DoubleTapGestureRecognizer extends GestureRecognizer {
}
}
String toStringShort() => 'double tap';
}
......@@ -385,4 +386,5 @@ class MultiTapGestureRecognizer extends GestureRecognizer {
_gestureArena = null;
}
String toStringShort() => 'multitap';
}
......@@ -42,6 +42,9 @@ abstract class GestureRecognizer extends GestureArenaMember {
/// GestureDetector widget calls this method).
void dispose() { }
/// Returns a very short pretty description of the gesture that the
/// recognizer looks for, like 'tap' or 'horizontal drag'.
String toStringShort() => toString();
}
/// Base class for gesture recognizers that can only recognize one
......
......@@ -135,4 +135,6 @@ class ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
}
_state = ScaleState.ready;
}
String toStringShort() => 'scale';
}
......@@ -102,4 +102,6 @@ class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
_wonArena = false;
_finalPosition = null;
}
String toStringShort() => 'tap';
}
......@@ -28,6 +28,8 @@ export 'package:flutter/gestures.dart' show
GestureScaleEndCallback,
Velocity;
typedef GestureRecognizer GestureRecognizerFactory(GestureRecognizer recognizer, PointerRouter router, GestureArena arena);
/// A widget that detects gestures.
///
/// Attempts to recognize gestures that correspond to its non-null callbacks.
......@@ -37,8 +39,8 @@ export 'package:flutter/gestures.dart' show
/// [excludeFromSemantics] to true.
///
/// See http://flutter.io/gestures/ for additional information.
class GestureDetector extends StatefulComponent {
const GestureDetector({
class GestureDetector extends StatelessComponent {
GestureDetector({
Key key,
this.child,
this.onTapDown,
......@@ -61,7 +63,23 @@ class GestureDetector extends StatefulComponent {
this.onScaleEnd,
this.behavior,
this.excludeFromSemantics: false
}) : super(key: key);
}) : super(key: key) {
assert(excludeFromSemantics != null);
assert(() {
bool haveVerticalDrag = onVerticalDragStart != null || onVerticalDragUpdate != null || onVerticalDragEnd != null;
bool haveHorizontalDrag = onHorizontalDragStart != null || onHorizontalDragUpdate != null || onHorizontalDragEnd != null;
bool havePan = onPanStart != null || onPanUpdate != null || onPanEnd != null;
bool haveScale = onScaleStart != null || onScaleUpdate != null || onScaleEnd != null;
if (havePan || haveScale) {
if (havePan && haveScale)
throw new WidgetError('Having both a pan gesture recognizer and a scale gesture recognizer is redundant; scale is a superset of pan. Just use the scale gesture recognizer.');
String recognizer = havePan ? 'pan' : 'scale';
if (haveVerticalDrag && haveHorizontalDrag)
throw new WidgetError('Simultaneously having a vertical drag gesture recognizer, a horizontal drag gesture recognizer, and a $recognizer gesture recognizer will result in the $recognizer gesture recognizer being ignored, since the other two will catch all drags.');
}
return true;
});
}
final Widget child;
......@@ -130,151 +148,192 @@ class GestureDetector extends StatefulComponent {
/// duplication of information.
final bool excludeFromSemantics;
_GestureDetectorState createState() => new _GestureDetectorState();
}
class _GestureDetectorState extends State<GestureDetector> {
PointerRouter get _router => Gesturer.instance.pointerRouter;
TapGestureRecognizer _tap;
DoubleTapGestureRecognizer _doubleTap;
LongPressGestureRecognizer _longPress;
VerticalDragGestureRecognizer _verticalDrag;
HorizontalDragGestureRecognizer _horizontalDrag;
PanGestureRecognizer _pan;
ScaleGestureRecognizer _scale;
Widget build(BuildContext context) {
Map<Type, GestureRecognizerFactory> gestures = <Type, GestureRecognizerFactory>{};
if (onTapDown != null || onTapUp != null || onTap != null || onTapCancel != null) {
gestures[TapGestureRecognizer] = (TapGestureRecognizer recognizer, PointerRouter router, GestureArena arena) {
return (recognizer ??= new TapGestureRecognizer(router: router, gestureArena: arena))
..onTapDown = onTapDown
..onTapUp = onTapUp
..onTap = onTap
..onTapCancel = onTapCancel;
};
}
void initState() {
super.initState();
_syncAll();
}
if (onDoubleTap != null) {
gestures[DoubleTapGestureRecognizer] = (DoubleTapGestureRecognizer recognizer, PointerRouter router, GestureArena arena) {
return (recognizer ??= new DoubleTapGestureRecognizer(router: router, gestureArena: arena))
..onDoubleTap = onDoubleTap;
};
}
void didUpdateConfig(GestureDetector oldConfig) {
_syncAll();
}
if (onLongPress != null) {
gestures[LongPressGestureRecognizer] = (LongPressGestureRecognizer recognizer, PointerRouter router, GestureArena arena) {
return (recognizer ??= new LongPressGestureRecognizer(router: router, gestureArena: arena))
..onLongPress = onLongPress;
};
}
void dispose() {
_tap = _ensureDisposed(_tap);
_doubleTap = _ensureDisposed(_doubleTap);
_longPress = _ensureDisposed(_longPress);
_verticalDrag = _ensureDisposed(_verticalDrag);
_horizontalDrag = _ensureDisposed(_horizontalDrag);
_pan = _ensureDisposed(_pan);
_scale = _ensureDisposed(_scale);
super.dispose();
}
if (onVerticalDragStart != null || onVerticalDragUpdate != null || onVerticalDragEnd != null) {
gestures[VerticalDragGestureRecognizer] = (VerticalDragGestureRecognizer recognizer, PointerRouter router, GestureArena arena) {
return (recognizer ??= new VerticalDragGestureRecognizer(router: router, gestureArena: arena))
..onStart = onVerticalDragStart
..onUpdate = onVerticalDragUpdate
..onEnd = onVerticalDragEnd;
};
}
void _syncAll() {
_syncTap();
_syncDoubleTap();
_syncLongPress();
_syncVerticalDrag();
_syncHorizontalDrag();
_syncPan();
_syncScale();
}
if (onHorizontalDragStart != null || onHorizontalDragUpdate != null || onHorizontalDragEnd != null) {
gestures[HorizontalDragGestureRecognizer] = (HorizontalDragGestureRecognizer recognizer, PointerRouter router, GestureArena arena) {
return (recognizer ??= new HorizontalDragGestureRecognizer(router: router, gestureArena: arena))
..onStart = onHorizontalDragStart
..onUpdate = onHorizontalDragUpdate
..onEnd = onHorizontalDragEnd;
};
}
void _syncTap() {
if (config.onTapDown == null && config.onTapUp == null && config.onTap == null && config.onTapCancel == null) {
_tap = _ensureDisposed(_tap);
} else {
_tap ??= new TapGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena);
_tap
..onTapDown = config.onTapDown
..onTapUp = config.onTapUp
..onTap = config.onTap
..onTapCancel = config.onTapCancel;
if (onPanStart != null || onPanUpdate != null || onPanEnd != null) {
gestures[PanGestureRecognizer] = (PanGestureRecognizer recognizer, PointerRouter router, GestureArena arena) {
return (recognizer ??= new PanGestureRecognizer(router: router, gestureArena: arena))
..onStart = onPanStart
..onUpdate = onPanUpdate
..onEnd = onPanEnd;
};
}
}
void _syncDoubleTap() {
if (config.onDoubleTap == null) {
_doubleTap = _ensureDisposed(_doubleTap);
} else {
_doubleTap ??= new DoubleTapGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena);
_doubleTap.onDoubleTap = config.onDoubleTap;
if (onScaleStart != null || onScaleUpdate != null || onScaleEnd != null) {
gestures[ScaleGestureRecognizer] = (ScaleGestureRecognizer recognizer, PointerRouter router, GestureArena arena) {
return (recognizer ??= new ScaleGestureRecognizer(router: router, gestureArena: arena))
..onStart = onScaleStart
..onUpdate = onScaleUpdate
..onEnd = onScaleEnd;
};
}
return new RawGestureDetector(
gestures: gestures,
behavior: behavior,
excludeFromSemantics: excludeFromSemantics,
child: child
);
}
}
void _syncLongPress() {
if (config.onLongPress == null) {
_longPress = _ensureDisposed(_longPress);
} else {
_longPress ??= new LongPressGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena);
_longPress.onLongPress = config.onLongPress;
}
/// A widget that detects gestures described by the given gesture
/// factories.
///
/// For common gestures, use a [GestureRecognizer].
/// RawGestureDetector is useful primarily when developing your
/// own gesture recognizers.
class RawGestureDetector extends StatefulComponent {
RawGestureDetector({
Key key,
this.child,
this.gestures: const <Type, GestureRecognizerFactory>{},
this.behavior,
this.excludeFromSemantics: false
}) : super(key: key) {
assert(gestures != null);
assert(excludeFromSemantics != null);
}
void _syncVerticalDrag() {
if (config.onVerticalDragStart == null && config.onVerticalDragUpdate == null && config.onVerticalDragEnd == null) {
_verticalDrag = _ensureDisposed(_verticalDrag);
} else {
_verticalDrag ??= new VerticalDragGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena);
_verticalDrag
..onStart = config.onVerticalDragStart
..onUpdate = config.onVerticalDragUpdate
..onEnd = config.onVerticalDragEnd;
}
final Widget child;
final Map<Type, GestureRecognizerFactory> gestures;
/// How this gesture detector should behave during hit testing.
final HitTestBehavior behavior;
/// Whether to exclude these gestures from the semantics tree. For
/// example, the long-press gesture for showing a tooltip is
/// excluded because the tooltip itself is included in the semantics
/// tree directly and so having a gesture to show it would result in
/// duplication of information.
final bool excludeFromSemantics;
RawGestureDetectorState createState() => new RawGestureDetectorState();
}
class RawGestureDetectorState extends State<RawGestureDetector> {
Map<Type, GestureRecognizer> _recognizers = const <Type, GestureRecognizer>{};
void initState() {
super.initState();
_syncAll(config.gestures);
}
void _syncHorizontalDrag() {
if (config.onHorizontalDragStart == null && config.onHorizontalDragUpdate == null && config.onHorizontalDragEnd == null) {
_horizontalDrag = _ensureDisposed(_horizontalDrag);
} else {
_horizontalDrag ??= new HorizontalDragGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena);
_horizontalDrag
..onStart = config.onHorizontalDragStart
..onUpdate = config.onHorizontalDragUpdate
..onEnd = config.onHorizontalDragEnd;
}
void didUpdateConfig(RawGestureDetector oldConfig) {
_syncAll(config.gestures);
}
void _syncPan() {
if (config.onPanStart == null && config.onPanUpdate == null && config.onPanEnd == null) {
_pan = _ensureDisposed(_pan);
} else {
assert(_scale == null); // Scale is a superset of pan; just use scale
_pan ??= new PanGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena);
_pan
..onStart = config.onPanStart
..onUpdate = config.onPanUpdate
..onEnd = config.onPanEnd;
/// This method can be called after the build phase, during the
/// layout of the nearest descendant RenderObjectWidget of the
/// gesture detector, to update the list of active gesture
/// recognizers.
///
/// The typical use case is [Scrollable]s, which put their viewport
/// in their gesture detector, and then need to know the dimensions
/// of the viewport and the viewport's child to determine whether
/// the gesture detector should be enabled.
void replaceGestureRecognizers(Map<Type, GestureRecognizerFactory> gestures) {
assert(() {
RenderObject renderObject = context.findRenderObject();
assert(renderObject is RenderPointerListener);
RenderPointerListener listener = renderObject;
RenderBox descendant = listener.child;
if (!config.excludeFromSemantics) {
assert(descendant is RenderSemanticsGestureHandler);
RenderSemanticsGestureHandler semanticsGestureHandler = descendant;
descendant = semanticsGestureHandler.child;
}
assert(descendant != null);
if (!descendant.debugDoingThisLayout) {
throw new WidgetError(
'replaceGestureRecognizers() can only be called during the layout phase of the GestureDetector\'s nearest descendant RenderObjectWidget.\n'
'In this particular case, that is:\n'
' $descendant'
);
}
return true;
});
_syncAll(gestures);
if (!config.excludeFromSemantics) {
RenderPointerListener listener = context.findRenderObject();
RenderSemanticsGestureHandler semanticsGestureHandler = listener.child;
context.visitChildElements((RenderObjectElement element) => element.widget.updateRenderObject(semanticsGestureHandler, null));
}
}
void _syncScale() {
if (config.onScaleStart == null && config.onScaleUpdate == null && config.onScaleEnd == null) {
_scale = _ensureDisposed(_scale);
} else {
assert(_pan == null); // Scale is a superset of pan; just use scale
_scale ??= new ScaleGestureRecognizer(router: _router, gestureArena: Gesturer.instance.gestureArena);
_scale
..onStart = config.onScaleStart
..onUpdate = config.onScaleUpdate
..onEnd = config.onScaleEnd;
}
void dispose() {
for (GestureRecognizer recognizer in _recognizers.values)
recognizer.dispose();
_recognizers = null;
super.dispose();
}
GestureRecognizer _ensureDisposed(GestureRecognizer recognizer) {
recognizer?.dispose();
return null;
void _syncAll(Map<Type, GestureRecognizerFactory> gestures) {
final PointerRouter pointerRouter = Gesturer.instance.pointerRouter;
final GestureArena gestureArena = Gesturer.instance.gestureArena;
assert(_recognizers != null);
Map<Type, GestureRecognizer> oldRecognizers = _recognizers;
_recognizers = <Type, GestureRecognizer>{};
for (Type type in gestures.keys) {
assert(!_recognizers.containsKey(type));
_recognizers[type] = gestures[type](oldRecognizers[type], pointerRouter, gestureArena);
assert(_recognizers[type].runtimeType == type);
}
for (Type type in oldRecognizers.keys) {
if (!_recognizers.containsKey(type))
oldRecognizers[type].dispose();
}
}
void _handlePointerDown(PointerDownEvent event) {
if (_tap != null)
_tap.addPointer(event);
if (_doubleTap != null)
_doubleTap.addPointer(event);
if (_longPress != null)
_longPress.addPointer(event);
if (_verticalDrag != null)
_verticalDrag.addPointer(event);
if (_horizontalDrag != null)
_horizontalDrag.addPointer(event);
if (_pan != null)
_pan.addPointer(event);
if (_scale != null)
_scale.addPointer(event);
assert(_recognizers != null);
for (GestureRecognizer recognizer in _recognizers.values)
recognizer.addPointer(event);
}
HitTestBehavior get _defaultBehavior {
......@@ -287,47 +346,21 @@ class _GestureDetectorState extends State<GestureDetector> {
behavior: config.behavior ?? _defaultBehavior,
child: config.child
);
if (!config.excludeFromSemantics) {
result = new _GestureSemantics(
onTapDown: config.onTapDown,
onTapUp: config.onTapUp,
onTap: config.onTap,
onLongPress: config.onLongPress,
onVerticalDragStart: config.onVerticalDragStart,
onVerticalDragUpdate: config.onVerticalDragUpdate,
onVerticalDragEnd: config.onVerticalDragEnd,
onHorizontalDragStart: config.onHorizontalDragStart,
onHorizontalDragUpdate: config.onHorizontalDragUpdate,
onHorizontalDragEnd: config.onHorizontalDragEnd,
onPanStart: config.onPanStart,
onPanUpdate: config.onPanUpdate,
onPanEnd: config.onPanEnd,
child: result
);
}
if (!config.excludeFromSemantics)
result = new _GestureSemantics(owner: this, child: result);
return result;
}
void debugFillDescription(List<String> description) {
super.debugFillDescription(description);
List<String> gestures = <String>[];
if (_tap != null)
gestures.add('tap');
if (_doubleTap != null)
gestures.add('double tap');
if (_longPress != null)
gestures.add('long press');
if (_verticalDrag != null)
gestures.add('vertical drag');
if (_horizontalDrag != null)
gestures.add('horizontal drag');
if (_pan != null)
gestures.add('pan');
if (_scale != null)
gestures.add('scale');
if (gestures.isEmpty)
gestures.add('<none>');
description.add('gestures: ${gestures.join(", ")}');
if (_recognizers == null) {
description.add('DISPOSED');
} else {
List<String> gestures = _recognizers.values.map/*<String>*/((GestureRecognizer recognizer) => recognizer.toStringShort());
if (gestures.isEmpty)
gestures.add('<none>');
description.add('gestures: ${gestures.join(", ")}');
}
switch (config.behavior) {
case HitTestBehavior.translucent:
description.add('behavior: translucent');
......@@ -345,118 +378,99 @@ class _GestureDetectorState extends State<GestureDetector> {
class _GestureSemantics extends OneChildRenderObjectWidget {
_GestureSemantics({
Key key,
this.onTapDown,
this.onTapUp,
this.onTap,
this.onLongPress,
this.onVerticalDragStart,
this.onVerticalDragUpdate,
this.onVerticalDragEnd,
this.onHorizontalDragStart,
this.onHorizontalDragUpdate,
this.onHorizontalDragEnd,
this.onPanStart,
this.onPanUpdate,
this.onPanEnd,
Widget child
Widget child,
this.owner
}) : super(key: key, child: child);
final GestureTapDownCallback onTapDown;
final GestureTapUpCallback onTapUp;
final GestureTapCallback onTap;
final GestureLongPressCallback onLongPress;
final GestureDragStartCallback onVerticalDragStart;
final GestureDragUpdateCallback onVerticalDragUpdate;
final GestureDragEndCallback onVerticalDragEnd;
final GestureDragStartCallback onHorizontalDragStart;
final GestureDragUpdateCallback onHorizontalDragUpdate;
final GestureDragEndCallback onHorizontalDragEnd;
final GesturePanStartCallback onPanStart;
final GesturePanUpdateCallback onPanUpdate;
final GesturePanEndCallback onPanEnd;
bool get _watchingTaps {
return onTapDown != null
|| onTapUp != null
|| onTap != null;
}
bool get _watchingHorizontalDrags {
return onHorizontalDragStart != null
|| onHorizontalDragUpdate != null
|| onHorizontalDragEnd != null;
}
final RawGestureDetectorState owner;
bool get _watchingVerticalDrags {
return onVerticalDragStart != null
|| onVerticalDragUpdate != null
|| onVerticalDragEnd != null;
}
bool get _watchingPans {
return onPanStart != null
|| onPanUpdate != null
|| onPanEnd != null;
void _handleTap() {
TapGestureRecognizer recognizer = owner._recognizers[TapGestureRecognizer];
assert(recognizer != null);
if (recognizer.onTapDown != null)
recognizer.onTapDown(Point.origin);
if (recognizer.onTapUp != null)
recognizer.onTapUp(Point.origin);
if (recognizer.onTap != null)
recognizer.onTap();
}
void _handleTap() {
if (onTapDown != null)
onTapDown(Point.origin);
if (onTapUp != null)
onTapUp(Point.origin);
if (onTap != null)
onTap();
void _handleLongPress() {
LongPressGestureRecognizer recognizer = owner._recognizers[LongPressGestureRecognizer];
assert(recognizer != null);
if (recognizer.onLongPress != null)
recognizer.onLongPress();
}
void _handleHorizontalDragUpdate(double delta) {
if (_watchingHorizontalDrags) {
if (onHorizontalDragStart != null)
onHorizontalDragStart(Point.origin);
if (onHorizontalDragUpdate != null)
onHorizontalDragUpdate(delta);
if (onHorizontalDragEnd != null)
onHorizontalDragEnd(Velocity.zero);
} else {
assert(_watchingPans);
if (onPanStart != null)
onPanStart(Point.origin);
if (onPanUpdate != null)
onPanUpdate(new Offset(delta, 0.0));
if (onPanEnd != null)
onPanEnd(Velocity.zero);
{
HorizontalDragGestureRecognizer recognizer = owner._recognizers[HorizontalDragGestureRecognizer];
if (recognizer != null) {
if (recognizer.onStart != null)
recognizer.onStart(Point.origin);
if (recognizer.onUpdate != null)
recognizer.onUpdate(delta);
if (recognizer.onEnd != null)
recognizer.onEnd(Velocity.zero);
return;
}
}
{
PanGestureRecognizer recognizer = owner._recognizers[PanGestureRecognizer];
if (recognizer != null) {
if (recognizer.onStart != null)
recognizer.onStart(Point.origin);
if (recognizer.onUpdate != null)
recognizer.onUpdate(new Offset(delta, 0.0));
if (recognizer.onEnd != null)
recognizer.onEnd(Velocity.zero);
return;
}
}
assert(false);
}
void _handleVerticalDragUpdate(double delta) {
if (_watchingVerticalDrags) {
if (onVerticalDragStart != null)
onVerticalDragStart(Point.origin);
if (onVerticalDragUpdate != null)
onVerticalDragUpdate(delta);
if (onVerticalDragEnd != null)
onVerticalDragEnd(Velocity.zero);
} else {
assert(_watchingPans);
if (onPanStart != null)
onPanStart(Point.origin);
if (onPanUpdate != null)
onPanUpdate(new Offset(0.0, delta));
if (onPanEnd != null)
onPanEnd(Velocity.zero);
{
VerticalDragGestureRecognizer recognizer = owner._recognizers[VerticalDragGestureRecognizer];
if (recognizer != null) {
if (recognizer.onStart != null)
recognizer.onStart(Point.origin);
if (recognizer.onUpdate != null)
recognizer.onUpdate(delta);
if (recognizer.onEnd != null)
recognizer.onEnd(Velocity.zero);
return;
}
}
{
PanGestureRecognizer recognizer = owner._recognizers[PanGestureRecognizer];
if (recognizer != null) {
if (recognizer.onStart != null)
recognizer.onStart(Point.origin);
if (recognizer.onUpdate != null)
recognizer.onUpdate(new Offset(0.0, delta));
if (recognizer.onEnd != null)
recognizer.onEnd(Velocity.zero);
return;
}
}
assert(false);
}
RenderSemanticsGestureHandler createRenderObject() => new RenderSemanticsGestureHandler(
onTap: _watchingTaps ? _handleTap : null,
onLongPress: onLongPress,
onHorizontalDragUpdate: _watchingHorizontalDrags || _watchingPans ? _handleHorizontalDragUpdate : null,
onVerticalDragUpdate: _watchingVerticalDrags || _watchingPans ? _handleVerticalDragUpdate : null
);
RenderSemanticsGestureHandler createRenderObject() {
RenderSemanticsGestureHandler result = new RenderSemanticsGestureHandler();
updateRenderObject(result, null);
return result;
}
void updateRenderObject(RenderSemanticsGestureHandler renderObject, _GestureSemantics oldWidget) {
renderObject.onTap = _watchingTaps ? _handleTap : null;
renderObject.onLongPress = onLongPress;
renderObject.onHorizontalDragUpdate = _watchingHorizontalDrags || _watchingPans ? _handleHorizontalDragUpdate : null;
renderObject.onVerticalDragUpdate = _watchingVerticalDrags || _watchingPans ? _handleVerticalDragUpdate : null;
Map<Type, GestureRecognizer> recognizers = owner._recognizers;
renderObject.onTap = recognizers.containsKey(TapGestureRecognizer) ? _handleTap : null;
renderObject.onLongPress = recognizers.containsKey(LongPressGestureRecognizer) ? _handleLongPress : null;
renderObject.onHorizontalDragUpdate = recognizers.containsKey(VerticalDragGestureRecognizer) ||
recognizers.containsKey(PanGestureRecognizer) ? _handleHorizontalDragUpdate : null;
renderObject.onVerticalDragUpdate = recognizers.containsKey(VerticalDragGestureRecognizer) ||
recognizers.containsKey(PanGestureRecognizer) ? _handleVerticalDragUpdate : null;
}
}
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