| OLD | NEW |
| 1 Sky Event Model | 1 Sky Event Model |
| 2 =============== | 2 =============== |
| 3 | 3 |
| 4 ```dart | 4 ```dart |
| 5 SKY MODULE | 5 SKY MODULE |
| 6 <!-- part of sky:core --> | 6 <!-- part of sky:core --> |
| 7 | 7 |
| 8 <script> | 8 <script> |
| 9 abstract class Event<ReturnType> { | 9 abstract class Event<ReturnType> { |
| 10 Event() { init(); } | 10 Event() { init(); } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 ReturnType result; | 22 ReturnType result; |
| 23 | 23 |
| 24 bool resultIsCompatible(dynamic candidate) => candidate is ReturnType; | 24 bool resultIsCompatible(dynamic candidate) => candidate is ReturnType; |
| 25 | 25 |
| 26 // TODO(ianh): abstract API for doing things at shadow tree boundaries | 26 // TODO(ianh): abstract API for doing things at shadow tree boundaries |
| 27 // TODO(ianh): do events get blocked at scope boundaries, e.g. focus events wh
en both sides are in the scope? | 27 // TODO(ianh): do events get blocked at scope boundaries, e.g. focus events wh
en both sides are in the scope? |
| 28 // TODO(ianh): do events get retargetted, e.g. focus when leaving a custom ele
ment? | 28 // TODO(ianh): do events get retargetted, e.g. focus when leaving a custom ele
ment? |
| 29 } | 29 } |
| 30 | 30 |
| 31 class EventTarget { | 31 class EventTarget { |
| 32 EventTarget() : _eventsController = new DispatcherController<Event>(); | 32 EventTarget() : _eventsController = new DispatcherController<@nonnull Event>()
; |
| 33 | 33 |
| 34 Dispatcher get events => _eventsController.dispatcher; | 34 Dispatcher get events => _eventsController.dispatcher; |
| 35 EventTarget parentNode; | 35 EventTarget parentNode; |
| 36 | 36 |
| 37 List<EventTarget> getEventDispatchChain() { | 37 List<@nonnull EventTarget> getEventDispatchChain() { |
| 38 if (this.parentNode == null) { | 38 if (this.parentNode == null) { |
| 39 return [this]; | 39 return [this]; |
| 40 } else { | 40 } else { |
| 41 var result = this.parentNode.getEventDispatchChain(); | 41 var result = this.parentNode.getEventDispatchChain(); |
| 42 result.insert(0, this); | 42 result.insert(0, this); |
| 43 return result; | 43 return result; |
| 44 } | 44 } |
| 45 } | 45 } |
| 46 | 46 |
| 47 final DispatcherController _eventsController; | 47 final DispatcherController _eventsController; |
| 48 | 48 |
| 49 dynamic dispatchEvent(Event event, { defaultResult: null }) { // O(N*M) where
N is the length of the chain and M is the average number of listeners per link i
n the chain | 49 dynamic dispatchEvent(@nonnull Event event, { dynamic defaultResult: null }) {
// O(N*M) where N is the length of the chain and M is the average number of lis
teners per link in the chain |
| 50 // note: this will throw an ExceptionListException<ExceptionListException> i
f any of the listeners threw | 50 // note: this will throw an ExceptionListException<ExceptionListException> i
f any of the listeners threw |
| 51 assert(event != null); // event must be non-null | 51 assert(event != null); // event must be non-null |
| 52 event.handled = false; | 52 event.handled = false; |
| 53 assert(event.resultIsCompatible(defaultResult)); | 53 assert(event.resultIsCompatible(defaultResult)); |
| 54 event.result = defaultResult; | 54 event.result = defaultResult; |
| 55 event._target = this; | 55 event._target = this; |
| 56 var chain; | 56 var chain; |
| 57 if (event.bubbles) | 57 if (event.bubbles) |
| 58 chain = this.getEventDispatchChain(); | 58 chain = this.getEventDispatchChain(); |
| 59 else | 59 else |
| 60 chain = [this]; | 60 chain = [this]; |
| 61 var exceptions = new ExceptionListException<ExceptionListException>(); | 61 var exceptions = new ExceptionListException<ExceptionListException>(); |
| 62 for (var link in chain) { | 62 for (var link in chain) { |
| 63 try { | 63 try { |
| 64 link._dispatchEventLocally(event); | 64 link._dispatchEventLocally(event); |
| 65 } on ExceptionListException catch (e) { | 65 } on ExceptionListException catch (e) { |
| 66 exceptions.add(e); | 66 exceptions.add(e); |
| 67 } | 67 } |
| 68 } | 68 } |
| 69 if (exceptions.length > 0) | 69 if (exceptions.length > 0) |
| 70 throw exceptions; | 70 throw exceptions; |
| 71 return event.result; | 71 return event.result; |
| 72 } | 72 } |
| 73 | 73 |
| 74 void _dispatchEventLocally(Event event) { | 74 void _dispatchEventLocally(@nonnull Event event) { |
| 75 event._currentTarget = this; | 75 event._currentTarget = this; |
| 76 _eventsController.add(event); | 76 _eventsController.add(event); |
| 77 } | 77 } |
| 78 } | 78 } |
| 79 </script> | 79 </script> |
| 80 ``` | 80 ``` |
| OLD | NEW |