@@ -45,6 +45,8 @@ class GestureArenaEntry {
|
||||
class _GestureArenaState {
|
||||
final List<GestureArenaMember> members = new List<GestureArenaMember>();
|
||||
bool isOpen = true;
|
||||
bool isHeld = false;
|
||||
bool hasPendingSweep = false;
|
||||
|
||||
void add(GestureArenaMember member) {
|
||||
assert(isOpen);
|
||||
@@ -72,6 +74,46 @@ class GestureArena {
|
||||
_tryToResolveArena(key, state);
|
||||
}
|
||||
|
||||
/// Force resolution on this arena, giving the win to the first member
|
||||
void sweep(Object key) {
|
||||
_GestureArenaState state = _arenas[key];
|
||||
if (state == null)
|
||||
return; // This arena either never existed or has been resolved.
|
||||
assert(!state.isOpen);
|
||||
if (state.isHeld) {
|
||||
state.hasPendingSweep = true;
|
||||
return; // This arena is being held for a long-lived member
|
||||
}
|
||||
_arenas.remove(key);
|
||||
if (!state.members.isEmpty) {
|
||||
// First member wins
|
||||
state.members.first.acceptGesture(key);
|
||||
// Give all the other members the bad news
|
||||
for (int i = 1; i < state.members.length; i++)
|
||||
state.members[i].rejectGesture(key);
|
||||
}
|
||||
}
|
||||
|
||||
/// Prevent the arena from being swept
|
||||
void hold(Object key) {
|
||||
_GestureArenaState state = _arenas[key];
|
||||
if (state == null)
|
||||
return; // This arena either never existed or has been resolved.
|
||||
state.isHeld = true;
|
||||
}
|
||||
|
||||
/// Release a hold, allowing the arena to be swept
|
||||
/// If a sweep was attempted on a held arena, the sweep will be done
|
||||
/// on release
|
||||
void release(Object key) {
|
||||
_GestureArenaState state = _arenas[key];
|
||||
if (state == null)
|
||||
return; // This arena either never existed or has been resolved.
|
||||
state.isHeld = false;
|
||||
if (state.hasPendingSweep)
|
||||
sweep(key);
|
||||
}
|
||||
|
||||
void _tryToResolveArena(Object key, _GestureArenaState state) {
|
||||
assert(_arenas[key] == state);
|
||||
assert(!state.isOpen);
|
||||
|
||||
@@ -244,6 +244,8 @@ class FlutterBinding extends HitTestTarget {
|
||||
pointerRouter.route(event);
|
||||
if (event.type == 'pointerdown')
|
||||
GestureArena.instance.close(event.pointer);
|
||||
else if (event.type == 'pointerup')
|
||||
GestureArena.instance.sweep(event.pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,4 +66,176 @@ void main() {
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isTrue);
|
||||
});
|
||||
|
||||
test('Should win by sweep', () {
|
||||
GestureArena arena = new GestureArena();
|
||||
|
||||
int primaryKey = 4;
|
||||
bool firstAcceptRan = false;
|
||||
bool firstRejectRan = false;
|
||||
bool secondAcceptRan = false;
|
||||
bool secondRejectRan = false;
|
||||
|
||||
TestGestureArenaMember first = new TestGestureArenaMember(
|
||||
onAcceptGesture: (int key) {
|
||||
expect(key, equals(primaryKey));
|
||||
firstAcceptRan = true;
|
||||
},
|
||||
onRejectGesture: (int key) {
|
||||
expect(key, equals(primaryKey));
|
||||
firstRejectRan = true;
|
||||
}
|
||||
);
|
||||
|
||||
TestGestureArenaMember second = new TestGestureArenaMember(
|
||||
onAcceptGesture: (int key) {
|
||||
expect(key, equals(primaryKey));
|
||||
secondAcceptRan = true;
|
||||
},
|
||||
onRejectGesture: (int key) {
|
||||
expect(key, equals(primaryKey));
|
||||
secondRejectRan = true;
|
||||
}
|
||||
);
|
||||
|
||||
arena.add(primaryKey, first);
|
||||
arena.add(primaryKey, second);
|
||||
arena.close(primaryKey);
|
||||
|
||||
expect(firstAcceptRan, isFalse);
|
||||
expect(firstRejectRan, isFalse);
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isFalse);
|
||||
|
||||
arena.sweep(primaryKey);
|
||||
|
||||
expect(firstAcceptRan, isTrue);
|
||||
expect(firstRejectRan, isFalse);
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isTrue);
|
||||
});
|
||||
|
||||
test('Should win on release after hold sweep release', () {
|
||||
GestureArena arena = new GestureArena();
|
||||
|
||||
int primaryKey = 4;
|
||||
bool firstAcceptRan = false;
|
||||
bool firstRejectRan = false;
|
||||
bool secondAcceptRan = false;
|
||||
bool secondRejectRan = false;
|
||||
|
||||
TestGestureArenaMember first = new TestGestureArenaMember(
|
||||
onAcceptGesture: (int key) {
|
||||
expect(key, equals(primaryKey));
|
||||
firstAcceptRan = true;
|
||||
},
|
||||
onRejectGesture: (int key) {
|
||||
expect(key, equals(primaryKey));
|
||||
firstRejectRan = true;
|
||||
}
|
||||
);
|
||||
|
||||
TestGestureArenaMember second = new TestGestureArenaMember(
|
||||
onAcceptGesture: (int key) {
|
||||
expect(key, equals(primaryKey));
|
||||
secondAcceptRan = true;
|
||||
},
|
||||
onRejectGesture: (int key) {
|
||||
expect(key, equals(primaryKey));
|
||||
secondRejectRan = true;
|
||||
}
|
||||
);
|
||||
|
||||
arena.add(primaryKey, first);
|
||||
arena.add(primaryKey, second);
|
||||
arena.close(primaryKey);
|
||||
|
||||
expect(firstAcceptRan, isFalse);
|
||||
expect(firstRejectRan, isFalse);
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isFalse);
|
||||
|
||||
arena.hold(primaryKey);
|
||||
|
||||
expect(firstAcceptRan, isFalse);
|
||||
expect(firstRejectRan, isFalse);
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isFalse);
|
||||
|
||||
arena.sweep(primaryKey);
|
||||
|
||||
expect(firstAcceptRan, isFalse);
|
||||
expect(firstRejectRan, isFalse);
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isFalse);
|
||||
|
||||
arena.release(primaryKey);
|
||||
|
||||
expect(firstAcceptRan, isTrue);
|
||||
expect(firstRejectRan, isFalse);
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isTrue);
|
||||
});
|
||||
|
||||
test('Should win on sweep after hold release sweep', () {
|
||||
GestureArena arena = new GestureArena();
|
||||
|
||||
int primaryKey = 4;
|
||||
bool firstAcceptRan = false;
|
||||
bool firstRejectRan = false;
|
||||
bool secondAcceptRan = false;
|
||||
bool secondRejectRan = false;
|
||||
|
||||
TestGestureArenaMember first = new TestGestureArenaMember(
|
||||
onAcceptGesture: (int key) {
|
||||
expect(key, equals(primaryKey));
|
||||
firstAcceptRan = true;
|
||||
},
|
||||
onRejectGesture: (int key) {
|
||||
expect(key, equals(primaryKey));
|
||||
firstRejectRan = true;
|
||||
}
|
||||
);
|
||||
|
||||
TestGestureArenaMember second = new TestGestureArenaMember(
|
||||
onAcceptGesture: (int key) {
|
||||
expect(key, equals(primaryKey));
|
||||
secondAcceptRan = true;
|
||||
},
|
||||
onRejectGesture: (int key) {
|
||||
expect(key, equals(primaryKey));
|
||||
secondRejectRan = true;
|
||||
}
|
||||
);
|
||||
|
||||
arena.add(primaryKey, first);
|
||||
arena.add(primaryKey, second);
|
||||
arena.close(primaryKey);
|
||||
|
||||
expect(firstAcceptRan, isFalse);
|
||||
expect(firstRejectRan, isFalse);
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isFalse);
|
||||
|
||||
arena.hold(primaryKey);
|
||||
|
||||
expect(firstAcceptRan, isFalse);
|
||||
expect(firstRejectRan, isFalse);
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isFalse);
|
||||
|
||||
arena.release(primaryKey);
|
||||
|
||||
expect(firstAcceptRan, isFalse);
|
||||
expect(firstRejectRan, isFalse);
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isFalse);
|
||||
|
||||
arena.sweep(primaryKey);
|
||||
|
||||
expect(firstAcceptRan, isTrue);
|
||||
expect(firstRejectRan, isFalse);
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isTrue);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user