mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add GestureArena
In the GestureArena, gestures will fight it out to see which is the real ultimate gesture.
This commit is contained in:
parent
c5809d658b
commit
03fffdfef9
64
sky/packages/sky/lib/gestures/arena.dart
Normal file
64
sky/packages/sky/lib/gestures/arena.dart
Normal file
@ -0,0 +1,64 @@
|
||||
// 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.
|
||||
|
||||
enum GestureDisposition {
|
||||
accepted,
|
||||
rejected
|
||||
}
|
||||
|
||||
abstract class GestureArenaMember {
|
||||
/// Called when this member wins the arena.
|
||||
void acceptGesture(Object key);
|
||||
|
||||
/// Called when this member loses the arena.
|
||||
void rejectGesture(Object key);
|
||||
}
|
||||
|
||||
class GestureArenaEntry {
|
||||
GestureArenaEntry._(this._arena, this._key, this._member);
|
||||
|
||||
final GestureArena _arena;
|
||||
final Object _key;
|
||||
final GestureArenaMember _member;
|
||||
|
||||
/// Call this member to claim victory (with accepted) or admit defeat (with rejected).
|
||||
void resolve(GestureDisposition disposition) {
|
||||
_arena._resolve(_key, _member, disposition);
|
||||
}
|
||||
}
|
||||
|
||||
/// The first member to accept or the last member to not to reject wins.
|
||||
class GestureArena {
|
||||
final Map<Object, List<GestureArenaMember>> _arenas = new Map<Object, List<GestureArenaMember>>();
|
||||
|
||||
GestureArenaEntry add(Object key, GestureArenaMember member) {
|
||||
List<GestureArenaMember> members = _arenas.putIfAbsent(key, () => new List<GestureArenaMember>());
|
||||
members.add(member);
|
||||
return new GestureArenaEntry._(this, key, member);
|
||||
}
|
||||
|
||||
void _resolve(Object key, GestureArenaMember member, GestureDisposition disposition) {
|
||||
List<GestureArenaMember> members = _arenas[key];
|
||||
assert(members != null);
|
||||
assert(members.contains(member));
|
||||
if (disposition == GestureDisposition.rejected) {
|
||||
members.remove(member);
|
||||
if (members.length == 1) {
|
||||
_arenas.remove(key);
|
||||
members.first.acceptGesture(key);
|
||||
} else if (members.isEmpty) {
|
||||
_arenas.remove(key);
|
||||
}
|
||||
} else {
|
||||
assert(disposition == GestureDisposition.accepted);
|
||||
List<GestureArenaMember> members = _arenas[key];
|
||||
_arenas.remove(key);
|
||||
for (GestureArenaMember rejectedMember in members) {
|
||||
if (rejectedMember != member)
|
||||
rejectedMember.rejectGesture(key);
|
||||
}
|
||||
member.acceptGesture(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
68
sky/unit/test/gestures/arena_test.dart
Normal file
68
sky/unit/test/gestures/arena_test.dart
Normal file
@ -0,0 +1,68 @@
|
||||
import 'package:sky/gestures/arena.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
typedef void GestureArenaCallback(Object key);
|
||||
|
||||
class TestGestureArenaMember extends GestureArenaMember {
|
||||
TestGestureArenaMember({ this.onAcceptGesture, this.onRejectGesture });
|
||||
|
||||
final GestureArenaCallback onAcceptGesture;
|
||||
final GestureArenaCallback onRejectGesture;
|
||||
|
||||
void acceptGesture(Object key) {
|
||||
onAcceptGesture(key);
|
||||
}
|
||||
|
||||
void rejectGesture(Object key) {
|
||||
onRejectGesture(key);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
test('Should win by accepting', () {
|
||||
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;
|
||||
}
|
||||
);
|
||||
|
||||
GestureArenaEntry firstEntry = arena.add(primaryKey, first);
|
||||
arena.add(primaryKey, second);
|
||||
|
||||
expect(firstAcceptRan, isFalse);
|
||||
expect(firstRejectRan, isFalse);
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isFalse);
|
||||
|
||||
firstEntry.resolve(GestureDisposition.accepted);
|
||||
|
||||
expect(firstAcceptRan, isTrue);
|
||||
expect(firstRejectRan, isFalse);
|
||||
expect(secondAcceptRan, isFalse);
|
||||
expect(secondRejectRan, isTrue);
|
||||
});
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user