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

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

Issue 16123029: Switching DOM events over to using StreamController. Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « tests/html/streams_test.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 /**
8 * Adapter for exposing DOM events as Dart streams.
9 */
10 class _EventStream<T extends Event> extends Stream<T> {
11 final EventTarget _target;
12 final String _eventType;
13 final bool _useCapture;
14
15 _EventStream(this._target, this._eventType, this._useCapture);
16
17 // DOM events are inherently multi-subscribers.
18 Stream<T> asBroadcastStream() => this;
19 bool get isBroadcast => true;
20
21 StreamSubscription<T> listen(void onData(T event),
22 { void onError(error),
23 void onDone(),
24 bool cancelOnError}) {
25
26 return new _EventStreamSubscription<T>(
27 this._target, this._eventType, onData, this._useCapture);
28 }
29 }
30
31 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
32 int _pauseCount = 0;
33 EventTarget _target;
34 final String _eventType;
35 var _onData;
36 final bool _useCapture;
37
38 _EventStreamSubscription(this._target, this._eventType, this._onData,
39 this._useCapture) {
40 _tryResume();
41 }
42
43 void cancel() {
44 if (_canceled) return;
45
46 _unlisten();
47 // Clear out the target to indicate this is complete.
48 _target = null;
49 _onData = null;
50 }
51
52 bool get _canceled => _target == null;
53
54 void onData(void handleData(T event)) {
55 if (_canceled) {
56 throw new StateError("Subscription has been canceled.");
57 }
58 // Remove current event listener.
59 _unlisten();
60
61 _onData = handleData;
62 _tryResume();
63 }
64
65 /// Has no effect.
66 void onError(void handleError(error)) {}
67
68 /// Has no effect.
69 void onDone(void handleDone()) {}
70
71 void pause([Future resumeSignal]) {
72 if (_canceled) return;
73 ++_pauseCount;
74 _unlisten();
75
76 if (resumeSignal != null) {
77 resumeSignal.whenComplete(resume);
78 }
79 }
80
81 bool get isPaused => _pauseCount > 0;
82
83 void resume() {
84 if (_canceled || !isPaused) return;
85 --_pauseCount;
86 _tryResume();
87 }
88
89 void _tryResume() {
90 if (_onData != null && !isPaused) {
91 _target.$dom_addEventListener(_eventType, _onData, _useCapture);
92 }
93 }
94
95 void _unlisten() {
96 if (_onData != null) {
97 _target.$dom_removeEventListener(_eventType, _onData, _useCapture);
98 }
99 }
100
101 Future asFuture([var futureValue]) {
102 // We just need a future that will never succeed or fail.
103 Completer completer = new Completer();
104 return completer.future;
105 }
106 }
107
108 7
109 /** 8 /**
110 * A factory to expose DOM events as Streams. 9 * A factory to expose DOM events as Streams.
111 */ 10 */
112 class EventStreamProvider<T extends Event> { 11 class EventStreamProvider<T extends Event> {
113 final String _eventType; 12 final String _eventType;
114 13
115 const EventStreamProvider(this._eventType); 14 const EventStreamProvider(this._eventType);
116 15
117 /** 16 /**
118 * Gets a [Stream] for this event type, on the specified target. 17 * Gets a [Stream] for this event type, on the specified target.
119 * 18 *
120 * This will always return a broadcast stream so multiple listeners can be 19 * This will always return a broadcast stream so multiple listeners can be
121 * used simultaneously. 20 * used simultaneously.
122 * 21 *
123 * This may be used to capture DOM events: 22 * This may be used to capture DOM events:
124 * 23 *
125 * Element.keyDownEvent.forTarget(element, useCapture: true).listen(...); 24 * Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
126 * 25 *
127 * Or for listening to an event which will bubble through the DOM tree: 26 * Or for listening to an event which will bubble through the DOM tree:
128 * 27 *
129 * MediaElement.pauseEvent.forTarget(document.body).listen(...); 28 * MediaElement.pauseEvent.forTarget(document.body).listen(...);
130 * 29 *
131 * See also: 30 * See also:
132 * 31 *
133 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener) 32 * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventLis tener)
134 */ 33 */
135 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) { 34 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) {
136 return new _EventStream(e, _eventType, useCapture); 35 var controller;
36
37 void onData(data) {
38 controller.add(data);
39 }
40
41 controller = new StreamController<T>(
42 onListen: () {
43 e.$dom_addEventListener(_eventType, onData, useCapture);
44 },
45 onCancel: () {
46 e.$dom_removeEventListener(_eventType, onData, useCapture);
47 },
48 sync: true);
49
50 return controller.stream;
137 } 51 }
138 52
139 /** 53 /**
140 * Gets the type of the event which this would listen for on the specified 54 * Gets the type of the event which this would listen for on the specified
141 * event target. 55 * event target.
142 * 56 *
143 * The target is necessary because some browsers may use different event names 57 * The target is necessary because some browsers may use different event names
144 * for the same purpose and the target allows differentiating browser support. 58 * for the same purpose and the target allows differentiating browser support.
145 */ 59 */
146 String getEventType(EventTarget target) { 60 String getEventType(EventTarget target) {
147 return _eventType; 61 return _eventType;
148 } 62 }
149 } 63 }
150 64
151 /** 65 /**
152 * A factory to expose DOM events as streams, where the DOM event name has to 66 * A factory to expose DOM events as streams, where the DOM event name has to
153 * be determined on the fly (for example, mouse wheel events). 67 * be determined on the fly (for example, mouse wheel events).
154 */ 68 */
155 class _CustomEventStreamProvider<T extends Event> 69 class _CustomEventStreamProvider<T extends Event>
156 implements EventStreamProvider<T> { 70 implements EventStreamProvider<T> {
157 71
158 final _eventTypeGetter; 72 final _eventTypeGetter;
159 const _CustomEventStreamProvider(this._eventTypeGetter); 73 const _CustomEventStreamProvider(this._eventTypeGetter);
160 74
161 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) { 75 Stream<T> forTarget(EventTarget e, {bool useCapture: false}) {
162 return new _EventStream(e, _eventTypeGetter(e), useCapture); 76 var controller;
77
78 var eventType = _eventTypeGetter(e);
79
80 void onData(data) {
81 controller.add(data);
82 }
83
84 controller = new StreamController<T>(
85 onListen: () {
86 e.$dom_addEventListener(eventType, onData, useCapture);
87 },
88 onCancel: () {
89 e.$dom_removeEventListener(eventType, onData, useCapture);
90 },
91 sync: true);
92
93 return controller.stream;
163 } 94 }
164 95
165 String getEventType(EventTarget target) { 96 String getEventType(EventTarget target) {
166 return _eventTypeGetter(target); 97 return _eventTypeGetter(target);
167 } 98 }
168 } 99 }
OLDNEW
« no previous file with comments | « tests/html/streams_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698