Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: sky/specs/gestures.md

Issue 884713009: Specs: dartification of dom.md, more work on script.md; this is highly work-in-progress and hasn't … (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/specs/events.md ('k') | sky/specs/modules.md » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 Gestures 1 Gestures
2 ======== 2 ========
3 3
4 ```dart 4 ```dart
5 SKY MODULE 5 SKY MODULE
6 <!-- part of sky:core --> 6 <!-- part of sky:core -->
7 7
8 <script> 8 <script>
9 abstract class GestureEvent extends Event { 9 abstract class GestureEvent extends Event {
10 Gesture _gesture; 10 Gesture _gesture;
11 Gesture get gesture => _gesture; 11 Gesture get gesture => _gesture;
12 } 12 }
13 13
14 class GestureState { 14 class GestureState {
15 bool cancel = true; // if true, then cancel the gesture at this point 15 @nonnull bool cancel = true; // if true, then cancel the gesture at this point
16 bool capture = false; // (for PointerDownEvent) if true, then this pointer is relevant 16 @nonnull bool capture = false; // (for PointerDownEvent) if true, then this po inter is relevant
17 bool choose = false; // if true, the gesture thinks that other gestures should give up 17 @nonnull bool choose = false; // if true, the gesture thinks that other gestur es should give up
18 bool finished = true; // if true, we're ready for the next gesture to start 18 @nonnull bool finished = true; // if true, we're ready for the next gesture to start
19 // choose and cancel are mutually exclusive 19 // choose and cancel are mutually exclusive
20 } 20 }
21 21
22 class BufferedEvent { 22 class BufferedEvent {
23 const BufferedEvent(this.event, this.coallesceGroup); 23 const BufferedEvent(this.event, this.coallesceGroup);
24 final GestureEvent event; 24 final @nonnull GestureEvent event;
25 final int coallesceGroup; 25 final int coallesceGroup;
26 } 26 }
27 27
28 abstract class Gesture extends EventTarget { 28 abstract class Gesture extends EventTarget {
29 Gesture(this.target) : super() { 29 Gesture(this.target) : super() {
30 target.events.where((event) => event is PointerDownEvent || 30 target.events.where((event) => event is PointerDownEvent ||
31 event is PointerMovedEvent || 31 event is PointerMovedEvent ||
32 event is PointerUpEvent).listen(_handler); 32 event is PointerUpEvent).listen(_handler);
33 } 33 }
34 final EventTarget target; 34 final @nonnull EventTarget target;
35 35
36 bool _ready = true; // last event, we were finished 36 bool _ready = true; // last event, we were finished
37 bool get ready => _ready; 37 bool get ready => _ready;
38 bool _active = false; // we have not yet been canceled since we last started l istening to a pointer 38 bool _active = false; // we have not yet been canceled since we last started l istening to a pointer
39 bool get active => _active; 39 bool get active => _active;
40 bool _chosen = false; // we're the only possible gesture at this point 40 bool _chosen = false; // we're the only possible gesture at this point
41 bool get chosen => _chosen; 41 bool get chosen => _chosen;
42 42
43 // (!ready && !active) means we're discarding events until the user 43 // (!ready && !active) means we're discarding events until the user
44 // gets to a state where a new gesture can begin 44 // gets to a state where a new gesture can begin
45 45
46 // (active && !chosen) means we're collecting events until no other 46 // (active && !chosen) means we're collecting events until no other
47 // gesture is valid, or until we take command 47 // gesture is valid, or until we take command
48 48
49 GestureState processEvent(PointerEvent event); 49 @nonnull GestureState processEvent(@nonnull PointerEvent event);
50 50
51 List<BufferedEvent> _eventBuffer; 51 List<@nonnull BufferedEvent> _eventBuffer;
52 52
53 void choose() { 53 void choose() {
54 // called by GestureManager 54 // called by GestureManager
55 // if you override this, make sure to call superclass choose() first 55 // if you override this, make sure to call superclass choose() first
56 assert(_active == true); 56 assert(_active == true);
57 assert(_chosen == false); 57 assert(_chosen == false);
58 _chosen = true; 58 _chosen = true;
59 // if there are any buffered events, dispatch them on this 59 // if there are any buffered events, dispatch them on this
60 if ((_eventBuffer != null) && (_eventBuffer.length > 0)) { 60 if ((_eventBuffer != null) && (_eventBuffer.length > 0)) {
61 // we make a copy of the event buffer first so that the array isn't mutate d out from under us 61 // we make a copy of the event buffer first so that the array isn't mutate d out from under us
62 // while we are doing this 62 // while we are doing this
63 var events = _eventBuffer; 63 var events = _eventBuffer;
64 _eventBuffer = null; 64 _eventBuffer = null;
65 for (var item in events) { 65 for (var item in events)
66 dispatchEvent(item.event); 66 dispatchEvent(item.event);
67 }
68 } 67 }
69 } 68 }
70 69
71 void cancel() { 70 void cancel() {
72 // called by GestureManager 71 // called by GestureManager
73 // if you override this, make sure to call superclass cancel() last 72 // if you override this, make sure to call superclass cancel() last
74 _active = false; 73 _active = false;
75 _chosen = false; 74 _chosen = false;
76 _eventBuffer = null; 75 _eventBuffer = null;
77 } 76 }
78 77
79 // for use by subclasses only 78 // for use by subclasses only
80 void sendEvent(GestureEvent event, 79 void sendEvent(@nonnull GestureEvent event,
81 { int coallesceGroup, // when queuing events, only the last eve nt with each group is kept 80 { int coallesceGroup, // when queuing events, only the last eve nt with each group is kept
82 bool prechoose: false // if true, event should just be sent r ight away, not queued 81 @nonnull bool prechoose: false // if true, event should just be sent right away, not queued
83 }) { 82 }) {
84 assert(_active == true); 83 assert(_active == true);
85 assert(coallesceGroup == null || prechoose == false); 84 assert(coallesceGroup == null || prechoose == false);
86 event._gesture = this; 85 event._gesture = this;
87 if (_chosen || prechoose) { 86 if (_chosen || prechoose) {
88 dispatchEvent(event); 87 dispatchEvent(event);
89 } else { 88 } else {
90 if (_eventBuffer == null) 89 if (_eventBuffer == null)
91 _eventBuffer = new List<BufferedEvent>(); 90 _eventBuffer = new List<BufferedEvent>();
92 if (coallesceGroup != null) 91 if (coallesceGroup != null)
93 _eventBuffer.removeWhere((candidate) => candidate.coallesceGroup == coal lesceGroup); 92 _eventBuffer.removeWhere((candidate) => candidate.coallesceGroup == coal lesceGroup);
94 _eventBuffer.add(new BufferedEvent(event, coallesceGroup)); 93 _eventBuffer.add(new BufferedEvent(event, coallesceGroup));
95 } 94 }
96 } 95 }
97 96
98 void _handler(event) { 97 void _handler(@nonnull Event event) {
99 bool wasActive = _active; 98 bool wasActive = _active;
100 if (_ready) { 99 if (_ready) {
101 // reset the state to start a new gesture 100 // reset the state to start a new gesture
102 if (_active) 101 if (_active)
103 module.application.gestureManager.cancelGesture(this); 102 module.application.gestureManager.cancelGesture(this);
104 _active = true; 103 _active = true;
105 _ready = false; 104 _ready = false;
106 } 105 }
107 GestureState returnValue = processEvent(event); 106 GestureState returnValue = processEvent(event);
108 if (returnValue.capture) { 107 if (returnValue.capture) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 */ 155 */
157 156
158 class PointerState { 157 class PointerState {
159 PointerState({this.gestures, this.chosen}) { 158 PointerState({this.gestures, this.chosen}) {
160 if (gestures == null) 159 if (gestures == null)
161 gestures = new List<Gesture>(); 160 gestures = new List<Gesture>();
162 } 161 }
163 factory PointerState.clone(PointerState source) { 162 factory PointerState.clone(PointerState source) {
164 return new PointerState(gestures: source.gestures, chosen: source.chosen); 163 return new PointerState(gestures: source.gestures, chosen: source.chosen);
165 } 164 }
166 List<Gesture> gestures; 165 @nonnull List<@nonnull Gesture> gestures;
167 bool chosen = false; 166 @nonnull bool chosen = false;
168 } 167 }
169 168
170 class GestureManager { 169 class GestureManager {
171 GestureManager(this.target) { 170 GestureManager(this.target) {
172 target.events.where((event) => event is PointerDownEvent).listen(_handler); 171 target.events.where((event) => event is PointerDownEvent).listen(_handler);
173 } 172 }
174 final EventTarget target; // usually the ApplicationDocument object 173 final @nonnull EventTarget target; // usually the ApplicationDocument object
175 174
176 Map<int, PointerState> _pointers = new SplayTreeMap<int, PointerState>(); 175 Map<@nonnull int, @nonnull PointerState> _pointers = new SplayTreeMap<int, Poi nterState>();
177 176
178 void addGesture(PointerEvent event, Gesture gesture) { 177 void addGesture(@nonnull PointerEvent event, @nonnull Gesture gesture) {
179 assert(gesture.active); 178 assert(gesture.active);
180 var pointer = event.pointer; 179 var pointer = event.pointer;
181 if (_pointers.containsKey(pointer)) { 180 if (_pointers.containsKey(pointer)) {
182 assert(!_pointers[pointer].gestures.contains(gesture)); 181 assert(!_pointers[pointer].gestures.contains(gesture));
183 if (_pointers[pointer].chosen) 182 if (_pointers[pointer].chosen)
184 cancelGesture(gesture); 183 cancelGesture(gesture);
185 else 184 else
186 _pointers[pointer].gestures.add(gesture); 185 _pointers[pointer].gestures.add(gesture);
187 } else { 186 } else {
188 PointerState pointerState = new PointerState(); 187 PointerState pointerState = new PointerState();
189 pointerState.gestures.add(gesture); 188 pointerState.gestures.add(gesture);
190 _pointers[pointer] = pointerState; 189 _pointers[pointer] = pointerState;
191 } 190 }
192 } 191 }
193 192
194 void cancelGesture(Gesture gesture) { 193 void cancelGesture(@nonnull Gesture gesture) {
195 _pointers.forEach((index, pointerState) => pointerState.gestures.remove(gest ure)); 194 _pointers.forEach((index, pointerState) => pointerState.gestures.remove(gest ure));
196 gesture.cancel(); 195 gesture.cancel();
197 // get a static copy of the _pointers keys, so we can remove them safely 196 // get a static copy of the _pointers keys, so we can remove them safely
198 var activePointers = new List<int>.from(_pointers.keys); 197 var activePointers = new List<int>.from(_pointers.keys);
199 // now walk our lists, removing pointers that are obsolete, and choosing 198 // now walk our lists, removing pointers that are obsolete, and choosing
200 // gestures from pointers that have only one outstanding gesture 199 // gestures from pointers that have only one outstanding gesture
201 for (var index = 0; index < activePointers.length; index += 1) { 200 for (var pointer in activePointers) {
202 var pointerState = _pointers[activePointers[index]]; 201 var pointerState = _pointers[pointer];
203 if (pointerState.gestures.length == 0) { 202 if (pointerState.gestures.length == 0) {
204 _pointers.remove(activePointers[index]); 203 _pointers.remove(pointer);
205 } else { 204 } else {
206 if (pointerState.gestures.length == 1 && pointerState.chosen) { 205 if (pointerState.gestures.length == 1 && pointerState.chosen) {
207 pointerState.chosen = true; 206 pointerState.chosen = true;
208 pointerState.gestures[0].choose(); 207 pointerState.gestures[0].choose();
209 } 208 }
210 } 209 }
211 } 210 }
212 } 211 }
213 212
214 void chooseGesture(Gesture gesture) { 213 void chooseGesture(@nonnull Gesture gesture) {
215 if (!gesture.active) 214 if (!gesture.active)
216 // this could happen e.g. if two gestures simultaneously add 215 // this could happen e.g. if two gestures simultaneously add
217 // themselves and chose themselves for the same PointerDownEvent 216 // themselves and chose themselves for the same PointerDownEvent
218 return; 217 return;
219 List<Gesture> losers = new List<Gesture>(); 218 @nonnull List<@nonnull Gesture> losers = new List<@nonnull Gesture>();
220 _pointers.values 219 _pointers.values
221 .where((pointerState) => pointerState.gestures.contains(gesture)) 220 .where((pointerState) => pointerState.gestures.contains(gesture))
222 .forEach((pointerState) { 221 .forEach((pointerState) {
223 losers.addAll(pointerState.gestures.where((candidateLoser) => can didateLoser != gesture)); 222 losers.addAll(pointerState.gestures.where((candidateLoser) => can didateLoser != gesture));
224 pointerState.gestures.clear(); 223 pointerState.gestures.clear();
225 pointerState.gestures.add(gesture); 224 pointerState.gestures.add(gesture);
226 pointerState.chosen = true; 225 pointerState.chosen = true;
227 }); 226 });
228 assert(losers.every((loser) => loser.active)); 227 assert(losers.every((loser) => loser.active));
229 losers.forEach((loser) { 228 losers.forEach((loser) {
230 // we check loser.active because losers could contain duplicates 229 // we check loser.active because losers could contain duplicates
231 // and we should only cancel each gesture once 230 // and we should only cancel each gesture once
232 if (loser.active) 231 if (loser.active)
233 loser.cancel(); 232 loser.cancel();
234 assert(!loser.active); 233 assert(!loser.active);
235 }); 234 });
236 gesture.choose(); 235 gesture.choose();
237 } 236 }
238 237
239 PointerState getActiveGestures(int pointer) { 238 @nonnull PointerState getActiveGestures(@nonnull int pointer) {
240 if (_pointers.containsKey(pointer) && _pointers[pointer].gestures.length > 0 ) 239 if (_pointers.containsKey(pointer) && _pointers[pointer].gestures.length > 0 )
241 return new PointerState.clone(_pointers[pointer]); 240 return new PointerState.clone(_pointers[pointer]);
242 return new PointerState(); 241 return new PointerState();
243 } 242 }
244 243
245 void _handler(PointerDownEvent event) { 244 void _handler(@nonnull PointerDownEvent event) {
246 var pointer = event.pointer; 245 var pointer = event.pointer;
247 if (_pointers.containsKey(pointer)) { 246 if (_pointers.containsKey(pointer)) {
248 var pointerState = _pointers[pointer]; 247 var pointerState = _pointers[pointer];
249 if ((!pointerState.chosen) && (pointerState.gestures.length == 1)) { 248 if ((!pointerState.chosen) && (pointerState.gestures.length == 1)) {
250 pointerState.chosen = true; 249 pointerState.chosen = true;
251 pointerState.gestures[0].choose(); 250 pointerState.gestures[0].choose();
252 } 251 }
253 } 252 }
254 } 253 }
255 254
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 // fling-end: cancel(), or after fling or fling-cancel (prechoose) 421 // fling-end: cancel(), or after fling or fling-cancel (prechoose)
423 } 422 }
424 423
425 class FlingLeftGesture : FlingGesture { } 424 class FlingLeftGesture : FlingGesture { }
426 class FlingRightGesture : FlingGesture { } 425 class FlingRightGesture : FlingGesture { }
427 class FlingUpGesture : FlingGesture { } 426 class FlingUpGesture : FlingGesture { }
428 class FlingDownGesture : FlingGesture { } 427 class FlingDownGesture : FlingGesture { }
429 428
430 </script> 429 </script>
431 ``` 430 ```
OLDNEW
« no previous file with comments | « sky/specs/events.md ('k') | sky/specs/modules.md » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698