Chromium Code Reviews| Index: runtime/embedders/openglui/common/gl.dart |
| =================================================================== |
| --- runtime/embedders/openglui/common/gl.dart (revision 19817) |
| +++ runtime/embedders/openglui/common/gl.dart (working copy) |
| @@ -67,8 +67,63 @@ |
| // Event handling. This is very kludgy for now, especially the |
| // bare-bones Stream stuff! |
| +typedef void EventListener(Event event); |
| + |
| +class EventTarget { |
| + static Map<EventTarget, Map<String, List<EventListener>>> _listeners = new Map(); |
|
vsm
2013/03/12 17:26:18
nit: length
gram
2013/03/12 17:47:14
Done.
|
| + |
| + static get listeners => _listeners; |
| + |
| + bool dispatchEvent(Event event) { |
| + if (!_listeners.containsKey(this)) return false; |
| + var listeners = _listeners[this]; |
| + if (!listeners.containsKey(event.type)) return false; |
| + var eventListeners = listeners[event.type]; |
| + for (var eventListener in eventListeners) { |
| + if (eventListener != null) { |
| + eventListener(event); |
| + } |
| + } |
| + return true; |
| + } |
| + |
| + void addListener(String eventType, EventListener handler) { |
| + if (!_listeners.containsKey(this)) { |
| + _listeners[this] = new Map(); |
| + } |
| + var listeners = _listeners[this]; |
| + if (!listeners.containsKey(eventType)) { |
| + listeners[eventType] = new List(); |
| + } |
| + var event_listeners = listeners[eventType]; |
| + for (var i = 0; i < event_listeners.length; i++) { |
| + if (event_listeners[i] == null) { |
| + event_listeners[i] = handler; |
| + return; |
| + } |
| + } |
| + event_listeners.add(handler); |
| + } |
| + |
| + void removeListener(String eventType, EventListener handler) { |
| + if (_listeners.containsKey(this)) { |
| + var listeners = _listeners[this]; |
| + if (listeners.containsKey(eventType)) { |
| + var event_listeners = listeners[eventType]; |
| + for (var i = 0; i < event_listeners.length; i++) { |
| + if (event_listeners[i] == handler) { |
| + event_listeners[i] = null; |
| + break; |
| + } |
| + } |
| + } |
| + } |
| + } |
| +} |
| + |
| class Event { |
| final String type; |
| + EventTarget target; |
| Event(String type) : this.type = type; |
| } |
| @@ -100,13 +155,10 @@ |
| } |
| } |
| -typedef void EventListener(Event event); |
| -Map<String,List<Function>> _listeners = new Map(); |
| - |
| class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> { |
| int _pauseCount = 0; |
| - Object _target; |
| + EventTarget _target; |
| final String _eventType; |
| var _onData; |
| @@ -171,31 +223,13 @@ |
| void _tryResume() { |
| if (_onData != null && !_paused) { |
| - if (!_listeners.containsKey(_eventType)) { |
| - _listeners[_eventType] = new List(); |
| - } |
| - var event_listeners = _listeners[_eventType]; |
| - for (var i = 0; i < event_listeners.length; i++) { |
| - if (event_listeners[i] == null) { |
| - event_listeners[i] = _onData; |
| - return; |
| - } |
| - } |
| - event_listeners.add(_onData); |
| + _target.addListener(_eventType, _onData); |
| } |
| } |
| void _unlisten() { |
| if (_onData != null) { |
| - if (!_listeners.containsKey(_eventType)) { |
| - var event_listeners = _listeners[_eventType]; |
| - for (var i = 0; i < event_listeners.length; i++) { |
| - if (event_listeners[i] == _onData) { |
| - event_listeners[i] = null; |
| - break; |
| - } |
| - } |
| - } |
| + _target.removeListener(_eventType, _onData); |
| } |
| } |
| } |
| @@ -220,7 +254,7 @@ |
| } |
| } |
| -class Node { |
| +class Node extends EventTarget { |
| Stream<KeyEvent> get onKeyDown => new _EventStream(this, 'keydown'); |
| Stream<KeyEvent> get onKeyUp => new _EventStream(this, 'keyup'); |
| Stream<MouseEvent> get onMouseDown => new _EventStream(this, 'mousedown'); |
| @@ -229,22 +263,26 @@ |
| } |
| // TODO(gram): If we support more than one on-screen canvas, we will |
| -// need to filter dispatched events by the target Node. |
| -_dispatchEvent(String event_type, Event e) { |
| - if (!_listeners.containsKey(event_type)) return; |
| - var event_listeners = _listeners[event_type]; |
| - for (var i = 0; i < event_listeners.length; i++) { |
| - if (event_listeners[i] != null) { |
| - event_listeners[i](e); |
| +// need to filter dispatched mouse and key events by the target Node |
| +// with more granularity; right now we just iterate through DOM nodes |
| +// until we find one that handles the event. |
| +_dispatchEvent(Event event) { |
| + assert(document.body.nodes.length <= 1); |
| + for (var target in document.body.nodes) { |
| + event.target = target; |
| + if (target.dispatchEvent(event)) { |
| + break; |
| } |
| } |
| } |
| -_dispatchKeyEvent(String type, int keyCode, bool alt, bool ctrl, bool shift) => |
| - _dispatchEvent(type, new KeyEvent(type, keyCode, alt, ctrl, shift)); |
| +_dispatchKeyEvent(String type, int keyCode, bool alt, bool ctrl, bool shift) { |
| + _dispatchEvent(new KeyEvent(type, keyCode, alt, ctrl, shift)); |
| +} |
| -_dispatchMouseEvent(String type, double x, double y) => |
| - _dispatchEvent(type, new MouseEvent(type, x.toInt(), y.toInt())); |
| +_dispatchMouseEvent(String type, double x, double y) { |
| + _dispatchEvent(new MouseEvent(type, x.toInt(), y.toInt())); |
| +} |
| // These next few are called by vmglue.cc. |
| onKeyDown_(int when, int keyCode, bool alt, bool ctrl, bool shift, int repeat) |
| @@ -607,15 +645,9 @@ |
| void C2DCreateNativeContext(int handle, int width, int height) |
| native "C2DCreateNativeContext"; |
| -class ElementEvents { |
| - final List load; |
| - ElementEvents() |
| - : load =new List() { |
| - } |
| -} |
| +class ImageElement extends Node { |
| + Stream<Event> get onLoad => new _EventStream(this, 'load'); |
| -class ImageElement { |
| - ElementEvents on; |
| String _src; |
| int _width; |
| int _height; |
| @@ -623,9 +655,9 @@ |
| get src => _src; |
| set src(String v) { |
| _src = v; |
| - for (var e in on.load) { |
| - e(this); |
| - } |
| + var e = new Event('load'); |
| + e.target = this; |
| + dispatchEvent(e); |
| } |
| get width => _width; |
| @@ -635,8 +667,7 @@ |
| set height(int heightp) => _height = heightp; |
| ImageElement({String srcp, int widthp, int heightp}) |
| - : on = new ElementEvents(), |
| - _src = srcp, |
| + : _src = srcp, |
| _width = widthp, |
| _height = heightp { |
| } |