Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library android_extension; | 5 library android_extension; |
| 6 import 'dart:async'; | 6 import 'dart:async'; |
| 7 | 7 |
| 8 // A VERY simplified DOM. | 8 // A VERY simplified DOM. |
| 9 | 9 |
| 10 class BodyElement { | 10 class BodyElement { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 Document document = new Document._internal(); | 60 Document document = new Document._internal(); |
| 61 | 61 |
| 62 // TODO(gram): make private and call from within library context. | 62 // TODO(gram): make private and call from within library context. |
| 63 update_() { | 63 update_() { |
| 64 window._dispatch(); | 64 window._dispatch(); |
| 65 } | 65 } |
| 66 | 66 |
| 67 // Event handling. This is very kludgy for now, especially the | 67 // Event handling. This is very kludgy for now, especially the |
| 68 // bare-bones Stream stuff! | 68 // bare-bones Stream stuff! |
| 69 | 69 |
| 70 class EventTarget extends Object { | |
|
vsm
2013/03/08 17:49:35
Nit: Don't need "extends Object".
gram
2013/03/11 21:25:08
Done.
| |
| 71 bool dispatchEvent(Event event) { | |
| 72 if (!_listeners.containsKey(this)) return false; | |
| 73 var listeners = _listeners[this]; | |
| 74 if (!listeners.containsKey(event.type)) return false; | |
| 75 var event_listeners = listeners[event.type]; | |
|
vsm
2013/03/08 17:49:35
event_listeners -> eventListeners per style guide
| |
| 76 for (var i = 0; i < event_listeners.length; i++) { | |
|
vsm
2013/03/08 17:49:35
Just iterate directly:
for (var eventListener in e
gram
2013/03/11 21:25:08
Will do, but is there a perf implication? I know t
| |
| 77 if (event_listeners[i] != null) { | |
| 78 event_listeners[i](event); | |
| 79 } | |
| 80 } | |
| 81 return true; | |
| 82 } | |
| 83 } | |
| 84 | |
| 70 class Event { | 85 class Event { |
| 71 final String type; | 86 final String type; |
| 87 EventTarget target; | |
| 72 Event(String type) : this.type = type; | 88 Event(String type) : this.type = type; |
| 73 } | 89 } |
| 74 | 90 |
| 75 class KeyEvent extends Event { | 91 class KeyEvent extends Event { |
| 76 final bool altKey; | 92 final bool altKey; |
| 77 final bool ctrlKey; | 93 final bool ctrlKey; |
| 78 final bool shiftKey; | 94 final bool shiftKey; |
| 79 final int keyCode; | 95 final int keyCode; |
| 80 | 96 |
| 81 KeyEvent(String type, int keycode, bool alt, bool ctrl, bool shift) | 97 KeyEvent(String type, int keycode, bool alt, bool ctrl, bool shift) |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 95 : super(type), | 111 : super(type), |
| 96 screenX = x, | 112 screenX = x, |
| 97 screenY = y, | 113 screenY = y, |
| 98 clientX = x, | 114 clientX = x, |
| 99 clientY = y { | 115 clientY = y { |
| 100 } | 116 } |
| 101 } | 117 } |
| 102 | 118 |
| 103 typedef void EventListener(Event event); | 119 typedef void EventListener(Event event); |
| 104 | 120 |
| 105 Map<String,List<Function>> _listeners = new Map(); | 121 Map<EventTarget, Map<String, List<Function>>> _listeners = new Map(); |
|
vsm
2013/03/08 17:49:35
Function -> EventListener ?
This might also be cl
gram
2013/03/11 21:25:08
Done.
| |
| 106 | 122 |
| 107 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> { | 123 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> { |
| 108 int _pauseCount = 0; | 124 int _pauseCount = 0; |
| 109 Object _target; | 125 EventTarget _target; |
| 110 final String _eventType; | 126 final String _eventType; |
| 111 var _onData; | 127 var _onData; |
| 112 | 128 |
| 113 _EventStreamSubscription(this._target, this._eventType, this._onData) { | 129 _EventStreamSubscription(this._target, this._eventType, this._onData) { |
| 114 _tryResume(); | 130 _tryResume(); |
| 115 } | 131 } |
| 116 | 132 |
| 117 void cancel() { | 133 void cancel() { |
| 118 if (_canceled) { | 134 if (_canceled) { |
| 119 throw new StateError("Subscription has been canceled."); | 135 throw new StateError("Subscription has been canceled."); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 164 } | 180 } |
| 165 if (!_paused) { | 181 if (!_paused) { |
| 166 throw new StateError("Subscription is not paused."); | 182 throw new StateError("Subscription is not paused."); |
| 167 } | 183 } |
| 168 --_pauseCount; | 184 --_pauseCount; |
| 169 _tryResume(); | 185 _tryResume(); |
| 170 } | 186 } |
| 171 | 187 |
| 172 void _tryResume() { | 188 void _tryResume() { |
| 173 if (_onData != null && !_paused) { | 189 if (_onData != null && !_paused) { |
| 174 if (!_listeners.containsKey(_eventType)) { | 190 if (!_listeners.containsKey(_target)) { |
| 175 _listeners[_eventType] = new List(); | 191 _listeners[_target] = new Map(); |
| 176 } | 192 } |
| 177 var event_listeners = _listeners[_eventType]; | 193 var listeners = _listeners[_target]; |
| 194 if (!listeners.containsKey(_eventType)) { | |
| 195 listeners[_eventType] = new List(); | |
| 196 } | |
| 197 var event_listeners = listeners[_eventType]; | |
| 178 for (var i = 0; i < event_listeners.length; i++) { | 198 for (var i = 0; i < event_listeners.length; i++) { |
| 179 if (event_listeners[i] == null) { | 199 if (event_listeners[i] == null) { |
| 180 event_listeners[i] = _onData; | 200 event_listeners[i] = _onData; |
| 181 return; | 201 return; |
| 182 } | 202 } |
| 183 } | 203 } |
| 184 event_listeners.add(_onData); | 204 event_listeners.add(_onData); |
| 185 } | 205 } |
| 186 } | 206 } |
| 187 | 207 |
| 188 void _unlisten() { | 208 void _unlisten() { |
| 189 if (_onData != null) { | 209 if (_onData != null) { |
| 190 if (!_listeners.containsKey(_eventType)) { | 210 if (_listeners.containsKey(_target)) { |
| 191 var event_listeners = _listeners[_eventType]; | 211 var listeners = _listeners[_target]; |
| 192 for (var i = 0; i < event_listeners.length; i++) { | 212 if (listeners.containsKey(_eventType)) { |
| 193 if (event_listeners[i] == _onData) { | 213 var event_listeners = listeners[_eventType]; |
| 194 event_listeners[i] = null; | 214 for (var i = 0; i < event_listeners.length; i++) { |
| 195 break; | 215 if (event_listeners[i] == _onData) { |
| 216 event_listeners[i] = null; | |
| 217 break; | |
| 218 } | |
| 196 } | 219 } |
| 197 } | 220 } |
| 198 } | 221 } |
| 199 } | 222 } |
| 200 } | 223 } |
| 201 } | 224 } |
| 202 | 225 |
| 203 class _EventStream<T extends Event> extends Stream<T> { | 226 class _EventStream<T extends Event> extends Stream<T> { |
| 204 final Object _target; | 227 final Object _target; |
| 205 final String _eventType; | 228 final String _eventType; |
| 206 | 229 |
| 207 _EventStream(this._target, this._eventType); | 230 _EventStream(this._target, this._eventType); |
| 208 | 231 |
| 209 // DOM events are inherently multi-subscribers. | 232 // DOM events are inherently multi-subscribers. |
| 210 Stream<T> asBroadcastStream() => this; | 233 Stream<T> asBroadcastStream() => this; |
| 211 bool get isBroadcast => true; | 234 bool get isBroadcast => true; |
| 212 | 235 |
| 213 StreamSubscription<T> listen(void onData(T event), | 236 StreamSubscription<T> listen(void onData(T event), |
| 214 { void onError(AsyncError error), | 237 { void onError(AsyncError error), |
| 215 void onDone(), | 238 void onDone(), |
| 216 bool unsubscribeOnError}) { | 239 bool unsubscribeOnError}) { |
| 217 | 240 |
| 218 return new _EventStreamSubscription<T>( | 241 return new _EventStreamSubscription<T>( |
| 219 this._target, this._eventType, onData); | 242 this._target, this._eventType, onData); |
| 220 } | 243 } |
| 221 } | 244 } |
| 222 | 245 |
| 223 class Node { | 246 class Node extends EventTarget { |
| 224 Stream<KeyEvent> get onKeyDown => new _EventStream(this, 'keydown'); | 247 Stream<KeyEvent> get onKeyDown => new _EventStream(this, 'keydown'); |
| 225 Stream<KeyEvent> get onKeyUp => new _EventStream(this, 'keyup'); | 248 Stream<KeyEvent> get onKeyUp => new _EventStream(this, 'keyup'); |
| 226 Stream<MouseEvent> get onMouseDown => new _EventStream(this, 'mousedown'); | 249 Stream<MouseEvent> get onMouseDown => new _EventStream(this, 'mousedown'); |
| 227 Stream<MouseEvent> get onMouseMove => new _EventStream(this, 'mousemove'); | 250 Stream<MouseEvent> get onMouseMove => new _EventStream(this, 'mousemove'); |
| 228 Stream<MouseEvent> get onMouseUp => new _EventStream(this, 'mouseup'); | 251 Stream<MouseEvent> get onMouseUp => new _EventStream(this, 'mouseup'); |
| 229 } | 252 } |
| 230 | 253 |
| 231 // TODO(gram): If we support more than one on-screen canvas, we will | 254 // TODO(gram): If we support more than one on-screen canvas, we will |
| 232 // need to filter dispatched events by the target Node. | 255 // need to filter dispatched mouse and key events by the target Node |
| 233 _dispatchEvent(String event_type, Event e) { | 256 // with more granularity; right now we just iterate through DOM nodes which shou ld |
|
vsm
2013/03/08 17:49:35
line len
gram
2013/03/11 21:25:08
Done.
| |
| 234 if (!_listeners.containsKey(event_type)) return; | 257 // just be the one canvas. |
|
vsm
2013/03/08 17:49:35
Should the code assert that there is just one canv
gram
2013/03/11 21:25:08
Done.
| |
| 235 var event_listeners = _listeners[event_type]; | 258 _dispatchEvent(Event event) { |
| 236 for (var i = 0; i < event_listeners.length; i++) { | 259 for (var target in document.body.nodes) { |
| 237 if (event_listeners[i] != null) { | 260 event.target = target; |
| 238 event_listeners[i](e); | 261 if (target.dispatchEvent(event)) { |
| 262 break; | |
| 239 } | 263 } |
| 240 } | 264 } |
| 241 } | 265 } |
| 242 | 266 |
| 243 _dispatchKeyEvent(String type, int keyCode, bool alt, bool ctrl, bool shift) => | 267 _dispatchKeyEvent(String type, int keyCode, bool alt, bool ctrl, bool shift) { |
| 244 _dispatchEvent(type, new KeyEvent(type, keyCode, alt, ctrl, shift)); | 268 _dispatchEvent(new KeyEvent(type, keyCode, alt, ctrl, shift)); |
| 269 } | |
| 245 | 270 |
| 246 _dispatchMouseEvent(String type, double x, double y) => | 271 _dispatchMouseEvent(String type, double x, double y) { |
| 247 _dispatchEvent(type, new MouseEvent(type, x.toInt(), y.toInt())); | 272 _dispatchEvent(new MouseEvent(type, x.toInt(), y.toInt())); |
| 273 } | |
| 248 | 274 |
| 249 // These next few are called by vmglue.cc. | 275 // These next few are called by vmglue.cc. |
| 250 onKeyDown_(int when, int keyCode, bool alt, bool ctrl, bool shift, int repeat) | 276 onKeyDown_(int when, int keyCode, bool alt, bool ctrl, bool shift, int repeat) |
| 251 => _dispatchKeyEvent('keydown', keyCode, alt, ctrl, shift); | 277 => _dispatchKeyEvent('keydown', keyCode, alt, ctrl, shift); |
| 252 | 278 |
| 253 onKeyUp_(int when, int keyCode, bool alt, bool ctrl, bool shift, int repeat) => | 279 onKeyUp_(int when, int keyCode, bool alt, bool ctrl, bool shift, int repeat) => |
| 254 _dispatchKeyEvent('keyup', keyCode, alt, ctrl, shift); | 280 _dispatchKeyEvent('keyup', keyCode, alt, ctrl, shift); |
| 255 | 281 |
| 256 onMouseDown_(int when, double x, double y) => | 282 onMouseDown_(int when, double x, double y) => |
| 257 _dispatchMouseEvent('mousedown', x, y); | 283 _dispatchMouseEvent('mousedown', x, y); |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 600 native "C2DStrokeText"; | 626 native "C2DStrokeText"; |
| 601 void C2DTransform(int handle, double m11, double m12, | 627 void C2DTransform(int handle, double m11, double m12, |
| 602 double m21, double m22, double dx, double dy) | 628 double m21, double m22, double dx, double dy) |
| 603 native "C2DTransform"; | 629 native "C2DTransform"; |
| 604 void C2DTranslate(int handle, double x, double y) | 630 void C2DTranslate(int handle, double x, double y) |
| 605 native "C2DTranslate"; | 631 native "C2DTranslate"; |
| 606 | 632 |
| 607 void C2DCreateNativeContext(int handle, int width, int height) | 633 void C2DCreateNativeContext(int handle, int width, int height) |
| 608 native "C2DCreateNativeContext"; | 634 native "C2DCreateNativeContext"; |
| 609 | 635 |
| 610 class ElementEvents { | 636 class ImageElement extends Node { |
| 611 final List load; | 637 Stream<Event> get onLoad => new _EventStream(this, 'load'); |
| 612 ElementEvents() | |
| 613 : load =new List() { | |
| 614 } | |
| 615 } | |
| 616 | 638 |
| 617 class ImageElement { | |
| 618 ElementEvents on; | |
| 619 String _src; | 639 String _src; |
| 620 int _width; | 640 int _width; |
| 621 int _height; | 641 int _height; |
| 622 | 642 |
| 623 get src => _src; | 643 get src => _src; |
| 624 set src(String v) { | 644 set src(String v) { |
| 625 _src = v; | 645 _src = v; |
| 626 for (var e in on.load) { | 646 var e = new Event('load'); |
| 627 e(this); | 647 e.target = this; |
| 628 } | 648 dispatchEvent(e); |
| 629 } | 649 } |
| 630 | 650 |
| 631 get width => _width; | 651 get width => _width; |
| 632 set width(int widthp) => _width = widthp; | 652 set width(int widthp) => _width = widthp; |
| 633 | 653 |
| 634 get height => _height; | 654 get height => _height; |
| 635 set height(int heightp) => _height = heightp; | 655 set height(int heightp) => _height = heightp; |
| 636 | 656 |
| 637 ImageElement({String srcp, int widthp, int heightp}) | 657 ImageElement({String srcp, int widthp, int heightp}) |
| 638 : on = new ElementEvents(), | 658 : _src = srcp, |
| 639 _src = srcp, | |
| 640 _width = widthp, | 659 _width = widthp, |
| 641 _height = heightp { | 660 _height = heightp { |
| 642 } | 661 } |
| 643 } | 662 } |
| 644 | 663 |
| 645 class ImageData { | 664 class ImageData { |
| 646 final Uint8ClampedArray data; | 665 final Uint8ClampedArray data; |
| 647 final int height; | 666 final int height; |
| 648 final int width; | 667 final int width; |
| 649 ImageData(this.height, this.width, this.data); | 668 ImageData(this.height, this.width, this.data); |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 995 num dirtyWidth, num dirtyHeight]) { | 1014 num dirtyWidth, num dirtyHeight]) { |
| 996 throw new Exception('Unimplemented webkitGetImageDataHD'); | 1015 throw new Exception('Unimplemented webkitGetImageDataHD'); |
| 997 } | 1016 } |
| 998 | 1017 |
| 999 // TODO(vsm): Kill. | 1018 // TODO(vsm): Kill. |
| 1000 noSuchMethod(invocation) { | 1019 noSuchMethod(invocation) { |
| 1001 throw new Exception('Unimplemented/unknown ${invocation.memberName}'); | 1020 throw new Exception('Unimplemented/unknown ${invocation.memberName}'); |
| 1002 } | 1021 } |
| 1003 } | 1022 } |
| 1004 | 1023 |
| OLD | NEW |