blob: 1b4a00d639479c6420d1267fb8cb014991cd609e [file] [log] [blame]
// 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
*/
}