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

Side by Side Diff: tools/dom/src/EventStreamProvider.dart

Issue 45313011: Refactor EventStreamProvider.dart to make flow make more sense. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « sdk/lib/html/dartium/html_dartium.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of html; 5 part of html;
6 6
7 /** 7 /**
8 * Adapter for exposing DOM events as Dart streams. 8 * A factory to expose DOM events as Streams.
9 */ 9 */
10 class _EventStream<T extends Event> extends Stream<T> { 10 class EventStreamProvider<T extends Event> {
11 final EventTarget _target;
12 final String _eventType; 11 final String _eventType;
13 final bool _useCapture;
14 12
15 _EventStream(this._target, this._eventType, this._useCapture); 13 const EventStreamProvider(this._eventType);
16 14
17 // DOM events are inherently multi-subscribers. 15 /**
18 Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription), 16 * Gets a [Stream] for this event type, on the specified target.
19 void onCancel(StreamSubscription subscription)}) 17 *
20 => this; 18 * This will always return a broadcast stream so multiple listeners can be
21 bool get isBroadcast => true; 19 * used simultaneously.
20 *
21 * This may be used to capture DOM events:
22 *
23 * Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
24 *
25 * // Alternate method:
26 * Element.keyDownEvent.forTarget(element).capture(...);
27 *
28 * Or for listening to an event which will bubble through the DOM tree:
29 *
30 * MediaElement.pauseEvent.forTarget(document.body).listen(...);
31 *
32 * See also:
33 *
34 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener)
35 */
36 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
37 new _EventStream(e, _eventType, useCapture);
22 38
23 StreamSubscription<T> listen(void onData(T event), 39 /**
24 { Function onError, 40 * Gets an [ElementEventStream] for this event type, on the specified element.
25 void onDone(), 41 *
26 bool cancelOnError}) { 42 * This will always return a broadcast stream so multiple listeners can be
43 * used simultaneously.
44 *
45 * This may be used to capture DOM events:
46 *
47 * Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
48 *
49 * // Alternate method:
50 * Element.keyDownEvent.forElement(element).capture(...);
51 *
52 * Or for listening to an event which will bubble through the DOM tree:
53 *
54 * MediaElement.pauseEvent.forElement(document.body).listen(...);
55 *
56 * See also:
57 *
58 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener)
59 */
60 ElementStream<T> forElement(Element e, {bool useCapture: false}) {
61 return new _ElementEventStreamImpl(e, _eventType, useCapture);
62 }
27 63
28 return new _EventStreamSubscription<T>( 64 /**
29 this._target, this._eventType, onData, this._useCapture); 65 * Gets an [ElementEventStream] for this event type, on the list of elements.
66 *
67 * This will always return a broadcast stream so multiple listeners can be
68 * used simultaneously.
69 *
70 * This may be used to capture DOM events:
71 *
72 * Element.keyDownEvent._forElementList(element, useCapture: true).listen( ...);
73 *
74 * See also:
75 *
76 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener)
77 */
78 ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
79 return new _ElementListEventStreamImpl(e, _eventType, useCapture);
80 }
81
82 /**
83 * Gets the type of the event which this would listen for on the specified
84 * event target.
85 *
86 * The target is necessary because some browsers may use different event names
87 * for the same purpose and the target allows differentiating browser support.
88 */
89 String getEventType(EventTarget target) {
90 return _eventType;
30 } 91 }
31 } 92 }
32 93
33 /** A specialized Stream available to [Element]s to enable event delegation. */ 94 /** A specialized Stream available to [Element]s to enable event delegation. */
34 abstract class ElementStream<T extends Event> implements Stream<T> { 95 abstract class ElementStream<T extends Event> implements Stream<T> {
35 /** 96 /**
36 * Return a stream that only fires when the particular event fires for 97 * Return a stream that only fires when the particular event fires for
37 * elements matching the specified CSS selector. 98 * elements matching the specified CSS selector.
38 * 99 *
39 * This is the Dart equivalent to jQuery's 100 * This is the Dart equivalent to jQuery's
(...skipping 12 matching lines...) Expand all
52 * ## Other resources 113 * ## Other resources
53 * 114 *
54 * * [Event Capture] 115 * * [Event Capture]
55 * (http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture) 116 * (http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture)
56 * from the W3C DOM Events specification. 117 * from the W3C DOM Events specification.
57 */ 118 */
58 StreamSubscription<T> capture(void onData(T event)); 119 StreamSubscription<T> capture(void onData(T event));
59 } 120 }
60 121
61 /** 122 /**
123 * Adapter for exposing DOM events as Dart streams.
124 */
125 class _EventStream<T extends Event> extends Stream<T> {
126 final EventTarget _target;
127 final String _eventType;
128 final bool _useCapture;
129
130 _EventStream(this._target, this._eventType, this._useCapture);
131
132 // DOM events are inherently multi-subscribers.
133 Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
134 void onCancel(StreamSubscription subscription)})
135 => this;
136 bool get isBroadcast => true;
137
138 StreamSubscription<T> listen(void onData(T event),
139 { Function onError,
140 void onDone(),
141 bool cancelOnError}) {
142
143 return new _EventStreamSubscription<T>(
144 this._target, this._eventType, onData, this._useCapture);
145 }
146 }
147
148 /**
62 * Adapter for exposing DOM Element events as streams, while also allowing 149 * Adapter for exposing DOM Element events as streams, while also allowing
63 * event delegation. 150 * event delegation.
64 */ 151 */
65 class _ElementEventStreamImpl<T extends Event> extends _EventStream<T> 152 class _ElementEventStreamImpl<T extends Event> extends _EventStream<T>
66 implements ElementStream<T> { 153 implements ElementStream<T> {
67 _ElementEventStreamImpl(target, eventType, useCapture) : 154 _ElementEventStreamImpl(target, eventType, useCapture) :
68 super(target, eventType, useCapture); 155 super(target, eventType, useCapture);
69 156
70 Stream<T> matches(String selector) => this.where( 157 Stream<T> matches(String selector) => this.where(
71 (event) => event.target.matchesWithAncestors(selector)).map((e) { 158 (event) => event.target.matchesWithAncestors(selector)).map((e) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 } 204 }
118 return pool.stream.listen(onData); 205 return pool.stream.listen(onData);
119 } 206 }
120 207
121 Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription), 208 Stream<T> asBroadcastStream({void onListen(StreamSubscription subscription),
122 void onCancel(StreamSubscription subscription)}) 209 void onCancel(StreamSubscription subscription)})
123 => this; 210 => this;
124 bool get isBroadcast => true; 211 bool get isBroadcast => true;
125 } 212 }
126 213
214 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
215 int _pauseCount = 0;
216 EventTarget _target;
217 final String _eventType;
218 var _onData;
219 final bool _useCapture;
220
221 _EventStreamSubscription(this._target, this._eventType, onData,
222 this._useCapture) : _onData = _wrapZone(onData) {
223 _tryResume();
224 }
225
226 void cancel() {
227 if (_canceled) return;
228
229 _unlisten();
230 // Clear out the target to indicate this is complete.
231 _target = null;
232 _onData = null;
233 }
234
235 bool get _canceled => _target == null;
236
237 void onData(void handleData(T event)) {
238 if (_canceled) {
239 throw new StateError("Subscription has been canceled.");
240 }
241 // Remove current event listener.
242 _unlisten();
243
244 _onData = _wrapZone(handleData);
245 _tryResume();
246 }
247
248 /// Has no effect.
249 void onError(Function handleError) {}
250
251 /// Has no effect.
252 void onDone(void handleDone()) {}
253
254 void pause([Future resumeSignal]) {
255 if (_canceled) return;
256 ++_pauseCount;
257 _unlisten();
258
259 if (resumeSignal != null) {
260 resumeSignal.whenComplete(resume);
261 }
262 }
263
264 bool get isPaused => _pauseCount > 0;
265
266 void resume() {
267 if (_canceled || !isPaused) return;
268 --_pauseCount;
269 _tryResume();
270 }
271
272 void _tryResume() {
273 if (_onData != null && !isPaused) {
274 _target.addEventListener(_eventType, _onData, _useCapture);
275 }
276 }
277
278 void _unlisten() {
279 if (_onData != null) {
280 _target.removeEventListener(_eventType, _onData, _useCapture);
281 }
282 }
283
284 Future asFuture([var futureValue]) {
285 // We just need a future that will never succeed or fail.
286 Completer completer = new Completer();
287 return completer.future;
288 }
289 }
290
127 /** 291 /**
128 * A stream of custom events, which enables the user to "fire" (add) their own 292 * A stream of custom events, which enables the user to "fire" (add) their own
129 * custom events to a stream. 293 * custom events to a stream.
130 */ 294 */
131 abstract class CustomStream<T extends Event> implements Stream<T> { 295 abstract class CustomStream<T extends Event> implements Stream<T> {
132 /** 296 /**
133 * Add the following custom event to the stream for dispatching to interested 297 * Add the following custom event to the stream for dispatching to interested
134 * listeners. 298 * listeners.
135 */ 299 */
136 void add(T event); 300 void add(T event);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 /** Removes all streams from this pool and closes [stream]. */ 394 /** Removes all streams from this pool and closes [stream]. */
231 void close() { 395 void close() {
232 for (var subscription in _subscriptions.values) { 396 for (var subscription in _subscriptions.values) {
233 subscription.cancel(); 397 subscription.cancel();
234 } 398 }
235 _subscriptions.clear(); 399 _subscriptions.clear();
236 _controller.close(); 400 _controller.close();
237 } 401 }
238 } 402 }
239 403
240 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
241 int _pauseCount = 0;
242 EventTarget _target;
243 final String _eventType;
244 var _onData;
245 final bool _useCapture;
246
247 _EventStreamSubscription(this._target, this._eventType, onData,
248 this._useCapture) : _onData = _wrapZone(onData) {
249 _tryResume();
250 }
251
252 void cancel() {
253 if (_canceled) return;
254
255 _unlisten();
256 // Clear out the target to indicate this is complete.
257 _target = null;
258 _onData = null;
259 }
260
261 bool get _canceled => _target == null;
262
263 void onData(void handleData(T event)) {
264 if (_canceled) {
265 throw new StateError("Subscription has been canceled.");
266 }
267 // Remove current event listener.
268 _unlisten();
269
270 _onData = _wrapZone(handleData);
271 _tryResume();
272 }
273
274 /// Has no effect.
275 void onError(Function handleError) {}
276
277 /// Has no effect.
278 void onDone(void handleDone()) {}
279
280 void pause([Future resumeSignal]) {
281 if (_canceled) return;
282 ++_pauseCount;
283 _unlisten();
284
285 if (resumeSignal != null) {
286 resumeSignal.whenComplete(resume);
287 }
288 }
289
290 bool get isPaused => _pauseCount > 0;
291
292 void resume() {
293 if (_canceled || !isPaused) return;
294 --_pauseCount;
295 _tryResume();
296 }
297
298 void _tryResume() {
299 if (_onData != null && !isPaused) {
300 _target.addEventListener(_eventType, _onData, _useCapture);
301 }
302 }
303
304 void _unlisten() {
305 if (_onData != null) {
306 _target.removeEventListener(_eventType, _onData, _useCapture);
307 }
308 }
309
310 Future asFuture([var futureValue]) {
311 // We just need a future that will never succeed or fail.
312 Completer completer = new Completer();
313 return completer.future;
314 }
315 }
316
317 /**
318 * A factory to expose DOM events as Streams.
319 */
320 class EventStreamProvider<T extends Event> {
321 final String _eventType;
322
323 const EventStreamProvider(this._eventType);
324
325 /**
326 * Gets a [Stream] for this event type, on the specified target.
327 *
328 * This will always return a broadcast stream so multiple listeners can be
329 * used simultaneously.
330 *
331 * This may be used to capture DOM events:
332 *
333 * Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
334 *
335 * // Alternate method:
336 * Element.keyDownEvent.forTarget(element).capture(...);
337 *
338 * Or for listening to an event which will bubble through the DOM tree:
339 *
340 * MediaElement.pauseEvent.forTarget(document.body).listen(...);
341 *
342 * See also:
343 *
344 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener)
345 */
346 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
347 new _EventStream(e, _eventType, useCapture);
348
349 /**
350 * Gets an [ElementEventStream] for this event type, on the specified element.
351 *
352 * This will always return a broadcast stream so multiple listeners can be
353 * used simultaneously.
354 *
355 * This may be used to capture DOM events:
356 *
357 * Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
358 *
359 * // Alternate method:
360 * Element.keyDownEvent.forElement(element).capture(...);
361 *
362 * Or for listening to an event which will bubble through the DOM tree:
363 *
364 * MediaElement.pauseEvent.forElement(document.body).listen(...);
365 *
366 * See also:
367 *
368 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener)
369 */
370 ElementStream<T> forElement(Element e, {bool useCapture: false}) {
371 return new _ElementEventStreamImpl(e, _eventType, useCapture);
372 }
373
374 /**
375 * Gets an [ElementEventStream] for this event type, on the list of elements.
376 *
377 * This will always return a broadcast stream so multiple listeners can be
378 * used simultaneously.
379 *
380 * This may be used to capture DOM events:
381 *
382 * Element.keyDownEvent._forElementList(element, useCapture: true).listen( ...);
383 *
384 * See also:
385 *
386 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener)
387 */
388 ElementStream<T> _forElementList(ElementList e, {bool useCapture: false}) {
389 return new _ElementListEventStreamImpl(e, _eventType, useCapture);
390 }
391
392 /**
393 * Gets the type of the event which this would listen for on the specified
394 * event target.
395 *
396 * The target is necessary because some browsers may use different event names
397 * for the same purpose and the target allows differentiating browser support.
398 */
399 String getEventType(EventTarget target) {
400 return _eventType;
401 }
402 }
403
404 /** 404 /**
405 * A factory to expose DOM events as streams, where the DOM event name has to 405 * A factory to expose DOM events as streams, where the DOM event name has to
406 * be determined on the fly (for example, mouse wheel events). 406 * be determined on the fly (for example, mouse wheel events).
407 */ 407 */
408 class _CustomEventStreamProvider<T extends Event> 408 class _CustomEventStreamProvider<T extends Event>
409 implements EventStreamProvider<T> { 409 implements EventStreamProvider<T> {
410 410
411 final _eventTypeGetter; 411 final _eventTypeGetter;
412 const _CustomEventStreamProvider(this._eventTypeGetter); 412 const _CustomEventStreamProvider(this._eventTypeGetter);
413 413
414 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) { 414 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) {
415 return new _EventStream(e, _eventTypeGetter(e), useCapture); 415 return new _EventStream(e, _eventTypeGetter(e), useCapture);
416 } 416 }
417 417
418 ElementStream<T> forElement(Element e, {bool useCapture: false}) { 418 ElementStream<T> forElement(Element e, {bool useCapture: false}) {
419 return new _ElementEventStreamImpl(e, _eventTypeGetter(e), useCapture); 419 return new _ElementEventStreamImpl(e, _eventTypeGetter(e), useCapture);
420 } 420 }
421 421
422 ElementStream<T> _forElementList(ElementList e, 422 ElementStream<T> _forElementList(ElementList e,
423 {bool useCapture: false}) { 423 {bool useCapture: false}) {
424 return new _ElementListEventStreamImpl(e, _eventTypeGetter(e), useCapture); 424 return new _ElementListEventStreamImpl(e, _eventTypeGetter(e), useCapture);
425 } 425 }
426 426
427 String getEventType(EventTarget target) { 427 String getEventType(EventTarget target) {
428 return _eventTypeGetter(target); 428 return _eventTypeGetter(target);
429 } 429 }
430 } 430 }
OLDNEW
« no previous file with comments | « sdk/lib/html/dartium/html_dartium.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698