Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c9a7149

Browse files
committed
Merge pull request #908 from abarth/gesture_arena
Add GestureArena
2 parents 68d9367 + 03fffdf commit c9a7149

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright 2015 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
enum GestureDisposition {
6+
accepted,
7+
rejected
8+
}
9+
10+
abstract class GestureArenaMember {
11+
/// Called when this member wins the arena.
12+
void acceptGesture(Object key);
13+
14+
/// Called when this member loses the arena.
15+
void rejectGesture(Object key);
16+
}
17+
18+
class GestureArenaEntry {
19+
GestureArenaEntry._(this._arena, this._key, this._member);
20+
21+
final GestureArena _arena;
22+
final Object _key;
23+
final GestureArenaMember _member;
24+
25+
/// Call this member to claim victory (with accepted) or admit defeat (with rejected).
26+
void resolve(GestureDisposition disposition) {
27+
_arena._resolve(_key, _member, disposition);
28+
}
29+
}
30+
31+
/// The first member to accept or the last member to not to reject wins.
32+
class GestureArena {
33+
final Map<Object, List<GestureArenaMember>> _arenas = new Map<Object, List<GestureArenaMember>>();
34+
35+
GestureArenaEntry add(Object key, GestureArenaMember member) {
36+
List<GestureArenaMember> members = _arenas.putIfAbsent(key, () => new List<GestureArenaMember>());
37+
members.add(member);
38+
return new GestureArenaEntry._(this, key, member);
39+
}
40+
41+
void _resolve(Object key, GestureArenaMember member, GestureDisposition disposition) {
42+
List<GestureArenaMember> members = _arenas[key];
43+
assert(members != null);
44+
assert(members.contains(member));
45+
if (disposition == GestureDisposition.rejected) {
46+
members.remove(member);
47+
if (members.length == 1) {
48+
_arenas.remove(key);
49+
members.first.acceptGesture(key);
50+
} else if (members.isEmpty) {
51+
_arenas.remove(key);
52+
}
53+
} else {
54+
assert(disposition == GestureDisposition.accepted);
55+
List<GestureArenaMember> members = _arenas[key];
56+
_arenas.remove(key);
57+
for (GestureArenaMember rejectedMember in members) {
58+
if (rejectedMember != member)
59+
rejectedMember.rejectGesture(key);
60+
}
61+
member.acceptGesture(key);
62+
}
63+
}
64+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import 'package:sky/gestures/arena.dart';
2+
import 'package:test/test.dart';
3+
4+
typedef void GestureArenaCallback(Object key);
5+
6+
class TestGestureArenaMember extends GestureArenaMember {
7+
TestGestureArenaMember({ this.onAcceptGesture, this.onRejectGesture });
8+
9+
final GestureArenaCallback onAcceptGesture;
10+
final GestureArenaCallback onRejectGesture;
11+
12+
void acceptGesture(Object key) {
13+
onAcceptGesture(key);
14+
}
15+
16+
void rejectGesture(Object key) {
17+
onRejectGesture(key);
18+
}
19+
}
20+
21+
void main() {
22+
test('Should win by accepting', () {
23+
GestureArena arena = new GestureArena();
24+
25+
int primaryKey = 4;
26+
bool firstAcceptRan = false;
27+
bool firstRejectRan = false;
28+
bool secondAcceptRan = false;
29+
bool secondRejectRan = false;
30+
31+
TestGestureArenaMember first = new TestGestureArenaMember(
32+
onAcceptGesture: (int key) {
33+
expect(key, equals(primaryKey));
34+
firstAcceptRan = true;
35+
},
36+
onRejectGesture: (int key) {
37+
expect(key, equals(primaryKey));
38+
firstRejectRan = true;
39+
}
40+
);
41+
42+
TestGestureArenaMember second = new TestGestureArenaMember(
43+
onAcceptGesture: (int key) {
44+
expect(key, equals(primaryKey));
45+
secondAcceptRan = true;
46+
},
47+
onRejectGesture: (int key) {
48+
expect(key, equals(primaryKey));
49+
secondRejectRan = true;
50+
}
51+
);
52+
53+
GestureArenaEntry firstEntry = arena.add(primaryKey, first);
54+
arena.add(primaryKey, second);
55+
56+
expect(firstAcceptRan, isFalse);
57+
expect(firstRejectRan, isFalse);
58+
expect(secondAcceptRan, isFalse);
59+
expect(secondRejectRan, isFalse);
60+
61+
firstEntry.resolve(GestureDisposition.accepted);
62+
63+
expect(firstAcceptRan, isTrue);
64+
expect(firstRejectRan, isFalse);
65+
expect(secondAcceptRan, isFalse);
66+
expect(secondRejectRan, isTrue);
67+
});
68+
}

0 commit comments

Comments
 (0)