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