OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
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. | |
4 | |
5 class EventsImplementation implements Events { | |
6 /* Raw event target. */ | |
7 var _ptr; | |
8 | |
9 Map<String, EventListenerList> _listenerMap; | |
10 | |
11 EventsImplementation._wrap(this._ptr) { | |
12 _listenerMap = <EventListenerList>{}; | |
13 } | |
14 | |
15 EventListenerList operator [](String type) { | |
16 return _get(type.toLowerCase()); | |
17 } | |
18 | |
19 EventListenerList _get(String type) { | |
20 return _listenerMap.putIfAbsent(type, | |
21 () => new EventListenerListImplementation(_ptr, type)); | |
22 } | |
23 } | |
24 | |
25 class _EventListenerWrapper { | |
26 final EventListener raw; | |
27 final Function wrapped; | |
28 final bool useCapture; | |
29 _EventListenerWrapper(this.raw, this.wrapped, this.useCapture); | |
30 } | |
31 | |
32 class EventListenerListImplementation implements EventListenerList { | |
33 final _ptr; | |
34 final String _type; | |
35 List<_EventListenerWrapper> _wrappers; | |
36 | |
37 EventListenerListImplementation(this._ptr, this._type) : | |
38 // TODO(jacobr): switch to <_EventListenerWrapper>[] when the VM allow it. | |
39 _wrappers = new List<_EventListenerWrapper>(); | |
40 | |
41 EventListenerList add(EventListener listener, [bool useCapture = false]) { | |
42 _add(listener, useCapture); | |
43 return this; | |
44 } | |
45 | |
46 EventListenerList remove(EventListener listener, [bool useCapture = false]) { | |
47 _remove(listener, useCapture); | |
48 return this; | |
49 } | |
50 | |
51 bool dispatch(Event evt) { | |
52 // TODO(jacobr): what is the correct behavior here. We could alternately | |
53 // force the event to have the expected type. | |
54 assert(evt.type == _type); | |
55 return _ptr.dispatchEvent(LevelDom.unwrap(evt)); | |
56 } | |
57 | |
58 void _add(EventListener listener, bool useCapture) { | |
59 _ptr.addEventListener(_type, | |
60 _findOrAddWrapper(listener, useCapture), | |
61 useCapture); | |
62 } | |
63 | |
64 void _remove(EventListener listener, bool useCapture) { | |
65 Function wrapper = _removeWrapper(listener, useCapture); | |
66 if (wrapper !== null) { | |
67 _ptr.removeEventListener(_type, wrapper, useCapture); | |
68 } | |
69 } | |
70 | |
71 Function _removeWrapper(EventListener listener, bool useCapture) { | |
72 if (_wrappers === null) { | |
73 return null; | |
74 } | |
75 for (int i = 0; i < _wrappers.length; i++) { | |
76 _EventListenerWrapper wrapper = _wrappers[i]; | |
77 if (wrapper.raw === listener && wrapper.useCapture == useCapture) { | |
78 // Order doesn't matter so we swap with the last element instead of | |
79 // performing a more expensive remove from the middle of the list. | |
80 if (i + 1 != _wrappers.length) { | |
81 _wrappers[i] = _wrappers.removeLast(); | |
82 } else { | |
83 _wrappers.removeLast(); | |
84 } | |
85 return wrapper.wrapped; | |
86 } | |
87 } | |
88 return null; | |
89 } | |
90 | |
91 Function _findOrAddWrapper(EventListener listener, bool useCapture) { | |
92 if (_wrappers === null) { | |
93 _wrappers = <_EventListenerWrapper>[]; | |
94 } else { | |
95 for (_EventListenerWrapper wrapper in _wrappers) { | |
96 if (wrapper.raw === listener && wrapper.useCapture == useCapture) { | |
97 return wrapper.wrapped; | |
98 } | |
99 } | |
100 } | |
101 final wrapped = (e) { listener(LevelDom.wrapEvent(e)); }; | |
102 _wrappers.add(new _EventListenerWrapper(listener, wrapped, useCapture)); | |
103 return wrapped; | |
104 } | |
105 } | |
106 | |
107 class EventTargetWrappingImplementation extends DOMWrapperBase implements EventT
arget { | |
108 Events _on; | |
109 | |
110 EventTargetWrappingImplementation._wrap(ptr) : super._wrap(ptr); | |
111 | |
112 Events get on() { | |
113 if (_on === null) { | |
114 _on = new EventsImplementation._wrap(_ptr); | |
115 } | |
116 return _on; | |
117 } | |
118 } | |
OLD | NEW |