| Index: tools/dom/src/EventStreamProvider.dart
|
| diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9c52a5dd7241f2f03d9b9c863e89c67b7fb64186
|
| --- /dev/null
|
| +++ b/tools/dom/src/EventStreamProvider.dart
|
| @@ -0,0 +1,137 @@
|
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +part of html;
|
| +
|
| +/**
|
| + * Adapter for exposing DOM events as Dart streams.
|
| + */
|
| +class _EventStream<T extends Event> extends Stream<T> {
|
| + final EventTarget _target;
|
| + final String _eventType;
|
| + final bool _useCapture;
|
| +
|
| + _EventStream(this._target, this._eventType, this._useCapture);
|
| +
|
| + // DOM events are inherently multi-subscribers.
|
| + Stream<T> asMultiSubscriberStream() => this;
|
| +
|
| + StreamSubscription<T> listen(void onData(T event),
|
| + { void onError(AsyncError error),
|
| + void onDone(),
|
| + bool unsubscribeOnError}) {
|
| +
|
| + return new _EventStreamSubscription<T>(
|
| + this._target, this._eventType, onData, this._useCapture);
|
| + }
|
| +}
|
| +
|
| +class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
|
| + int _pauseCount = 0;
|
| + EventTarget _target;
|
| + final String _eventType;
|
| + var _onData;
|
| + final bool _useCapture;
|
| +
|
| + _EventStreamSubscription(this._target, this._eventType, this._onData,
|
| + this._useCapture) {
|
| + _tryResume();
|
| + }
|
| +
|
| + void cancel() {
|
| + if (_canceled) {
|
| + throw new StateError("Subscription has been canceled.");
|
| + }
|
| +
|
| + _unlisten();
|
| + // Clear out the target to indicate this is complete.
|
| + _target = null;
|
| + _onData = null;
|
| + }
|
| +
|
| + bool get _canceled => _target == null;
|
| +
|
| + void onData(void handleData(T event)) {
|
| + if (_canceled) {
|
| + throw new StateError("Subscription has been canceled.");
|
| + }
|
| + // Remove current event listener.
|
| + _unlisten();
|
| +
|
| + _onData = handleData;
|
| + _tryResume();
|
| + }
|
| +
|
| + /// Has no effect.
|
| + void onError(void handleError(AsyncError error)) {}
|
| +
|
| + /// Has no effect.
|
| + void onDone(void handleDone()) {}
|
| +
|
| + void pause([Future resumeSignal]) {
|
| + if (_canceled) {
|
| + throw new StateError("Subscription has been canceled.");
|
| + }
|
| + ++_pauseCount;
|
| + _unlisten();
|
| +
|
| + if (resumeSignal != null) {
|
| + resumeSignal.whenComplete(resume);
|
| + }
|
| + }
|
| +
|
| + bool get _paused => _pauseCount > 0;
|
| +
|
| + void resume() {
|
| + if (_canceled) {
|
| + throw new StateError("Subscription has been canceled.");
|
| + }
|
| + if (!_paused) {
|
| + throw new StateError("Subscription is not paused.");
|
| + }
|
| + --_pauseCount;
|
| + _tryResume();
|
| + }
|
| +
|
| + void _tryResume() {
|
| + if (_onData != null && !_paused) {
|
| + _target.$dom_addEventListener(_eventType, _onData, _useCapture);
|
| + }
|
| + }
|
| +
|
| + void _unlisten() {
|
| + if (_onData != null) {
|
| + _target.$dom_removeEventListener(_eventType, _onData, _useCapture);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +/**
|
| + * A factory to expose DOM events as Streams.
|
| + */
|
| +class EventStreamProvider<T extends Event> {
|
| + final String _eventType;
|
| +
|
| + const EventStreamProvider(this._eventType);
|
| +
|
| + /**
|
| + * Gets a [Stream] for this event type, on the specified target.
|
| + *
|
| + * This may be used to capture DOM events:
|
| + *
|
| + * Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
|
| + *
|
| + * Or for listening to an event which will bubble through the DOM tree:
|
| + *
|
| + * MediaElement.pauseEvent.forTarget(document.body).listen(...);
|
| + *
|
| + * See also:
|
| + *
|
| + * [addEventListener](http://docs.webplatform.org/wiki/dom/methods/addEventListener)
|
| + */
|
| + Stream<T> forTarget(EventTarget e, {bool useCapture: false}) {
|
| + return new _EventStream(e, _eventType, useCapture);
|
| + }
|
| +}
|
|
|