| // Copyright (c) 2012, 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. |
| |
| class _EventsImpl implements Events { |
| // TODO(podivilov): add type. |
| final _ptr; |
| |
| final Map<String, EventListenerList> _listenerMap; |
| |
| _EventsImpl(this._ptr) : _listenerMap = <EventListenerList>{}; |
| |
| EventListenerList operator [](String type) { |
| return _listenerMap.putIfAbsent(type, |
| () => new _EventListenerListImpl(_ptr, type)); |
| } |
| } |
| |
| class _EventListenerWrapper { |
| final EventListener raw; |
| final Function wrapped; |
| final bool useCapture; |
| _EventListenerWrapper(this.raw, this.wrapped, this.useCapture); |
| } |
| |
| class _EventListenerListImpl implements EventListenerList { |
| // TODO(podivilov): add type. |
| final _ptr; |
| final String _type; |
| List<_EventListenerWrapper> _wrappers; |
| |
| _EventListenerListImpl(this._ptr, this._type) : |
| // TODO(jacobr): switch to <_EventListenerWrapper>[] when the VM allow it. |
| _wrappers = new List<_EventListenerWrapper>(); |
| |
| EventListenerList add(EventListener listener, [bool useCapture = false]) { |
| _add(listener, useCapture); |
| return this; |
| } |
| |
| EventListenerList remove(EventListener listener, [bool useCapture = false]) { |
| _remove(listener, useCapture); |
| return this; |
| } |
| |
| bool dispatch(Event evt) { |
| // TODO(jacobr): what is the correct behavior here. We could alternately |
| // force the event to have the expected type. |
| assert(evt.type == _type); |
| return _ptr.$dom_dispatchEvent(evt); |
| } |
| |
| void _add(EventListener listener, bool useCapture) { |
| _ptr.$dom_addEventListener(_type, |
| _findOrAddWrapper(listener, useCapture), |
| useCapture); |
| } |
| |
| void _remove(EventListener listener, bool useCapture) { |
| Function wrapper = _removeWrapper(listener, useCapture); |
| if (wrapper !== null) { |
| _ptr.$dom_removeEventListener(_type, wrapper, useCapture); |
| } |
| } |
| |
| Function _removeWrapper(EventListener listener, bool useCapture) { |
| if (_wrappers === null) { |
| return null; |
| } |
| for (int i = 0; i < _wrappers.length; i++) { |
| _EventListenerWrapper wrapper = _wrappers[i]; |
| if (wrapper.raw === listener && wrapper.useCapture == useCapture) { |
| // Order doesn't matter so we swap with the last element instead of |
| // performing a more expensive remove from the middle of the list. |
| if (i + 1 != _wrappers.length) { |
| _wrappers[i] = _wrappers.removeLast(); |
| } else { |
| _wrappers.removeLast(); |
| } |
| return wrapper.wrapped; |
| } |
| } |
| return null; |
| } |
| |
| Function _findOrAddWrapper(EventListener listener, bool useCapture) { |
| if (_wrappers === null) { |
| _wrappers = <_EventListenerWrapper>[]; |
| } else { |
| for (_EventListenerWrapper wrapper in _wrappers) { |
| if (wrapper.raw === listener && wrapper.useCapture == useCapture) { |
| return wrapper.wrapped; |
| } |
| } |
| } |
| final wrapped = (e) { listener(e); }; |
| _wrappers.add(new _EventListenerWrapper(listener, wrapped, useCapture)); |
| return wrapped; |
| } |
| } |
| |
| class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { |
| /* |
| $!MEMBERS |
| */ |
| } |