OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
3 # for details. All rights reserved. Use of this source code is governed by a | 3 # for details. All rights reserved. Use of this source code is governed by a |
4 # BSD-style license that can be found in the LICENSE file. | 4 # BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 """This module provides functionality to generate dart:html event classes.""" | 6 """This module provides functionality to generate dart:html event classes.""" |
7 | 7 |
8 import logging | 8 import logging |
9 | 9 |
10 _logger = logging.getLogger('dartgenerator') | 10 _logger = logging.getLogger('dartgenerator') |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 'webkitSpeechChange': 'speechChange', | 175 'webkitSpeechChange': 'speechChange', |
176 'webkitsourceclose': 'sourceClose', | 176 'webkitsourceclose': 'sourceClose', |
177 'webkitsourceended': 'sourceEnded', | 177 'webkitsourceended': 'sourceEnded', |
178 'webkitsourceopen': 'sourceOpen', | 178 'webkitsourceopen': 'sourceOpen', |
179 'webkitTransitionEnd': 'transitionEnd', | 179 'webkitTransitionEnd': 'transitionEnd', |
180 'write': 'write', | 180 'write': 'write', |
181 'writeend': 'writeEnd', | 181 'writeend': 'writeEnd', |
182 'writestart': 'writeStart' | 182 'writestart': 'writeStart' |
183 } | 183 } |
184 | 184 |
185 _html_event_types = { | |
186 '*.abort': ('abort', 'Event'), | |
187 '*.beforecopy': ('beforeCopy', 'Event'), | |
188 '*.beforecut': ('beforeCut', 'Event'), | |
189 '*.beforepaste': ('beforePaste', 'Event'), | |
190 '*.beforeunload': ('beforeUnload', 'Event'), | |
191 '*.blur': ('blur', 'Event'), | |
192 '*.canplay': ('canPlay', 'Event'), | |
193 '*.canplaythrough': ('canPlayThrough', 'Event'), | |
194 '*.change': ('change', 'Event'), | |
195 '*.click': ('click', 'MouseEvent'), | |
196 '*.contextmenu': ('contextMenu', 'MouseEvent'), | |
197 '*.copy': ('copy', 'Event'), | |
198 '*.cut': ('cut', 'Event'), | |
199 '*.dblclick': ('doubleClick', 'Event'), | |
200 '*.drag': ('drag', 'MouseEvent'), | |
201 '*.dragend': ('dragEnd', 'MouseEvent'), | |
202 '*.dragenter': ('dragEnter', 'MouseEvent'), | |
203 '*.dragleave': ('dragLeave', 'MouseEvent'), | |
204 '*.dragover': ('dragOver', 'MouseEvent'), | |
205 '*.dragstart': ('dragStart', 'MouseEvent'), | |
206 '*.drop': ('drop', 'MouseEvent'), | |
207 '*.durationchange': ('durationChange', 'Event'), | |
208 '*.emptied': ('emptied', 'Event'), | |
209 '*.ended': ('ended', 'Event'), | |
210 '*.error': ('error', 'Event'), | |
211 '*.focus': ('focus', 'Event'), | |
212 '*.hashchange': ('hashChange', 'HashChangeEvent'), | |
213 '*.input': ('input', 'Event'), | |
214 '*.invalid': ('invalid', 'Event'), | |
215 '*.keydown': ('keyDown', 'KeyboardEvent'), | |
216 '*.keypress': ('keyPress', 'KeyboardEvent'), | |
217 '*.keyup': ('keyUp', 'KeyboardEvent'), | |
218 '*.load': ('load', 'Event'), | |
219 '*.loadeddata': ('loadedData', 'Event'), | |
220 '*.loadedmetadata': ('loadedMetadata', 'Event'), | |
221 '*.message': ('message', 'MessageEvent'), | |
222 '*.mousedown': ('mouseDown', 'MouseEvent'), | |
223 '*.mousemove': ('mouseMove', 'MouseEvent'), | |
224 '*.mouseout': ('mouseOut', 'MouseEvent'), | |
225 '*.mouseover': ('mouseOver', 'MouseEvent'), | |
226 '*.mouseup': ('mouseUp', 'MouseEvent'), | |
227 '*.mousewheel': ('mouseWheel', 'WheelEvent'), | |
228 '*.offline': ('offline', 'Event'), | |
229 '*.online': ('online', 'Event'), | |
230 '*.paste': ('paste', 'Event'), | |
231 '*.pause': ('pause', 'Event'), | |
232 '*.play': ('play', 'Event'), | |
233 '*.playing': ('playing', 'Event'), | |
234 '*.popstate': ('popState', 'PopStateEvent'), | |
235 '*.ratechange': ('rateChange', 'Event'), | |
236 '*.reset': ('reset', 'Event'), | |
237 '*.resize': ('resize', 'Event'), | |
238 '*.scroll': ('scroll', 'Event'), | |
239 '*.search': ('search', 'Event'), | |
240 '*.seeked': ('seeked', 'Event'), | |
241 '*.seeking': ('seeking', 'Event'), | |
242 '*.select': ('select', 'Event'), | |
243 '*.selectstart': ('selectStart', 'Event'), | |
244 '*.stalled': ('stalled', 'Event'), | |
245 '*.storage': ('storage', 'StorageEvent'), | |
246 '*.submit': ('submit', 'Event'), | |
247 '*.suspend': ('suspend', 'Event'), | |
248 '*.timeupdate': ('timeUpdate', 'Event'), | |
249 '*.touchcancel': ('touchCancel', 'TouchEvent'), | |
250 '*.touchend': ('touchEnd', 'TouchEvent'), | |
251 '*.touchenter': ('touchEnter', 'TouchEvent'), | |
252 '*.touchleave': ('touchLeave', 'TouchEvent'), | |
253 '*.touchmove': ('touchMove', 'TouchEvent'), | |
254 '*.touchstart': ('touchStart', 'TouchEvent'), | |
255 '*.unload': ('unload', 'Event'), | |
256 '*.volumechange': ('volumeChange', 'Event'), | |
257 '*.waiting': ('waiting', 'Event'), | |
258 '*.webkitAnimationEnd': ('animationEnd', 'AnimationEvent'), | |
259 '*.webkitAnimationIteration': ('animationIteration', 'AnimationEvent'), | |
260 '*.webkitAnimationStart': ('animationStart', 'AnimationEvent'), | |
261 '*.webkitTransitionEnd': ('transitionEnd', 'TransitionEvent'), | |
262 '*.webkitfullscreenchange': ('fullscreenChange', 'Event'), | |
263 '*.webkitfullscreenerror': ('fullscreenError', 'Event'), | |
264 'AudioContext.complete': ('complete', 'Event'), | |
265 'BatteryManager.chargingchange': ('chargingChange', 'Event'), | |
266 'BatteryManager.chargingtimechange': ('chargingTimeChange', 'Event'), | |
267 'BatteryManager.dischargingtimechange': ('dischargingTimeChange', 'Event'), | |
268 'BatteryManager.levelchange': ('levelChange', 'Event'), | |
269 'DOMApplicationCache.cached': ('cached', 'Event'), | |
270 'DOMApplicationCache.checking': ('checking', 'Event'), | |
271 'DOMApplicationCache.downloading': ('downloading', 'Event'), | |
272 'DOMApplicationCache.noupdate': ('noUpdate', 'Event'), | |
273 'DOMApplicationCache.obsolete': ('obsolete', 'Event'), | |
274 'DOMApplicationCache.progress': ('progress', 'Event'), | |
275 'DOMApplicationCache.updateready': ('updateReady', 'Event'), | |
276 'Document.cuechange': ('cueChange', 'Event'), | |
277 'Document.readystatechange': ('readyStateChange', 'Event'), | |
278 'Document.selectionchange': ('selectionChange', 'Event'), | |
279 'Document.webkitpointerlockchange': ('pointerLockChange', 'Event'), | |
280 'Document.webkitpointerlockerror': ('pointerLockError', 'Event'), | |
281 'Element.cuechange': ('cueChange', 'Event'), | |
282 'EventSource.open': ('open', 'Event'), | |
283 'FileReader.abort': ('abort', 'ProgressEvent'), | |
284 'FileReader.load': ('load', 'ProgressEvent'), | |
285 'FileReader.loadend': ('loadEnd', 'ProgressEvent'), | |
286 'FileReader.loadstart': ('loadStart', 'ProgressEvent'), | |
287 'FileReader.progress': ('progress', 'ProgressEvent'), | |
288 'FileWriter.abort': ('abort', 'ProgressEvent'), | |
289 'FileWriter.progress': ('progress', 'ProgressEvent'), | |
290 'FileWriter.write': ('write', 'ProgressEvent'), | |
291 'FileWriter.writeend': ('writeEnd', 'ProgressEvent'), | |
292 'FileWriter.writestart': ('writeStart', 'ProgressEvent'), | |
293 'HTMLBodyElement.storage': ('storage', 'StorageEvent'), | |
294 'HTMLInputElement.webkitSpeechChange': ('speechChange', 'Event'), | |
295 'HTMLMediaElement.loadstart': ('loadStart', 'Event'), | |
296 'HTMLMediaElement.progress': ('progress', 'Event'), | |
297 'HTMLMediaElement.show': ('show', 'Event'), | |
298 'HTMLMediaElement.webkitkeyadded': ('keyAdded', 'MediaKeyEvent'), | |
299 'HTMLMediaElement.webkitkeyerror': ('keyError', 'MediaKeyEvent'), | |
300 'HTMLMediaElement.webkitkeymessage': ('keyMessage', 'MediaKeyEvent'), | |
301 'HTMLMediaElement.webkitneedkey': ('needKey', 'MediaKeyEvent'), | |
302 'IDBDatabase.versionchange': ('versionChange', 'UpgradeNeededEvent'), | |
303 'IDBOpenDBRequest.blocked': ('blocked', 'Event'), | |
304 'IDBOpenDBRequest.upgradeneeded': ('upgradeNeeded', 'VersionChangeEvent'), | |
305 'IDBRequest.success': ('success', 'Event'), | |
306 'IDBTransaction.complete': ('complete', 'Event'), | |
307 'IDBVersionChangeRequest.blocked': ('blocked', 'Event'), | |
308 'MediaController.play': ('play', 'Event'), | |
309 'MediaStreamTrack.mute': ('mute', 'Event'), | |
310 'MediaStreamTrack.unmute': ('unmute', 'Event'), | |
311 'MediaStreamTrackList.addtrack': ('addTrack', 'MediaStreamTrackEvent'), | |
312 'MediaStreamTrackList.removetrack': ('removeTrack', 'MediaStreamTrackEvent'), | |
313 'Notification.click': ('click', 'Event'), | |
314 'Notification.close': ('close', 'Event'), | |
315 'Notification.display': ('display', 'Event'), | |
316 'Notification.show': ('show', 'Event'), | |
317 'RTCDataChannel.close': ('close', 'Event'), | |
318 'RTCDataChannel.open': ('open', 'Event'), | |
319 'RTCPeerConnection.addstream': ('addStream', 'MediaStreamEvent'), | |
320 'RTCPeerConnection.connecting': ('connecting', 'MediaStreamEvent'), | |
321 'RTCPeerConnection.datachannel': ('dataChannel', 'RtcDataChannelEvent'), | |
322 'RTCPeerConnection.icecandidate': ('iceCandidate', 'RtcIceCandidateEvent'), | |
323 'RTCPeerConnection.icechange': ('iceChange', 'Event'), | |
324 'RTCPeerConnection.negotiationneeded': ('negotiationNeeded', 'Event'), | |
325 'RTCPeerConnection.open': ('open', 'Event'), | |
326 'RTCPeerConnection.removestream': ('removeStream', 'MediaStreamEvent'), | |
327 'RTCPeerConnection.statechange': ('stateChange', 'Event'), | |
328 'ScriptProcessorNode.audioprocess': ('audioProcess', 'AudioProcessingEvent'), | |
329 'SharedWorkerContext.connect': ('connect', 'Event'), | |
330 'SpeechRecognition.audioend': ('audioEnd', 'Event'), | |
331 'SpeechRecognition.audiostart': ('audioStart', 'Event'), | |
332 'SpeechRecognition.end': ('end', 'Event'), | |
333 'SpeechRecognition.error': ('error', 'SpeechRecognitionError'), | |
334 'SpeechRecognition.nomatch': ('noMatch', 'SpeechRecognitionEvent'), | |
335 'SpeechRecognition.result': ('result', 'SpeechRecognitionEvent'), | |
336 'SpeechRecognition.soundend': ('soundEnd', 'Event'), | |
337 'SpeechRecognition.soundstart': ('soundStart', 'Event'), | |
338 'SpeechRecognition.speechend': ('speechEnd', 'Event'), | |
339 'SpeechRecognition.speechstart': ('speechStart', 'Event'), | |
340 'SpeechRecognition.start': ('start', 'Event'), | |
341 'TextTrack.cuechange': ('cueChange', 'Event'), | |
342 'TextTrackCue.enter': ('enter', 'Event'), | |
343 'TextTrackCue.exit': ('exit', 'Event'), | |
344 'TextTrackList.addtrack': ('addTrack', 'TrackEvent'), | |
345 'WebSocket.close': ('close', 'CloseEvent'), | |
346 'WebSocket.open': ('open', 'Event'), # should be OpenEvent, but not exposed. | |
347 'Window.DOMContentLoaded': ('contentLoaded', 'Event'), | |
348 'Window.cuechange': ('cueChange', 'Event'), | |
349 'Window.devicemotion': ('deviceMotion', 'DeviceMotionEvent'), | |
350 'Window.deviceorientation': ('deviceOrientation', 'DeviceOrientationEvent'), | |
351 'Window.loadstart': ('loadStart', 'Event'), | |
352 'Window.pagehide': ('pageHide', 'Event'), | |
353 'Window.pageshow': ('pageShow', 'Event'), | |
354 'Window.progress': ('progress', 'Event'), | |
355 'XMLHttpRequest.abort': ('abort', 'ProgressEvent'), | |
356 'XMLHttpRequest.error': ('error', 'ProgressEvent'), | |
357 'XMLHttpRequest.load': ('load', 'ProgressEvent'), | |
358 'XMLHttpRequest.loadend': ('loadEnd', 'ProgressEvent'), | |
359 'XMLHttpRequest.loadstart': ('loadStart', 'ProgressEvent'), | |
360 'XMLHttpRequest.progress': ('progress', 'ProgressEvent'), | |
361 'XMLHttpRequest.readystatechange': ('readyStateChange', 'ProgressEvent'), | |
362 'XMLHttpRequestUpload.abort': ('abort', 'ProgressEvent'), | |
363 'XMLHttpRequestUpload.error': ('error', 'ProgressEvent'), | |
364 'XMLHttpRequestUpload.load': ('load', 'ProgressEvent'), | |
365 'XMLHttpRequestUpload.loadend': ('loadEnd', 'ProgressEvent'), | |
366 'XMLHttpRequestUpload.loadstart': ('loadStart', 'ProgressEvent'), | |
367 'XMLHttpRequestUpload.progress': ('progress', 'ProgressEvent'), | |
368 } | |
369 | |
185 # These classes require an explicit declaration for the "on" method even though | 370 # These classes require an explicit declaration for the "on" method even though |
186 # they don't declare any unique events, because the concrete class hierarchy | 371 # they don't declare any unique events, because the concrete class hierarchy |
187 # doesn't match the interface hierarchy. | 372 # doesn't match the interface hierarchy. |
188 _html_explicit_event_classes = set(['DocumentFragment']) | 373 _html_explicit_event_classes = set(['DocumentFragment']) |
189 | 374 |
190 class HtmlEventGenerator(object): | 375 class HtmlEventGenerator(object): |
191 | 376 |
192 def __init__(self, database, renamer, template_loader): | 377 def __init__(self, database, renamer, template_loader): |
193 self._event_classes = set() | 378 self._event_classes = set() |
194 self._database = database | 379 self._database = database |
195 self._renamer = renamer | 380 self._renamer = renamer |
196 self._template_loader = template_loader | 381 self._template_loader = template_loader |
197 | 382 |
383 def EmitStreamProviders(self, interface, html_interface_name, custom_events, | |
384 members_emitter): | |
385 events = self._GetEvents(interface, html_interface_name, custom_events) | |
386 if not events: | |
387 return | |
388 | |
389 for event_info in events: | |
390 (dom_name, html_name, event_type) = event_info | |
391 members_emitter.Emit( | |
392 "\n" | |
393 " static const HtmlStreamProvider<$TYPE> $(NAME)Event = " | |
394 "const HtmlStreamProvider<$TYPE>('$DOM_NAME');\n", | |
395 NAME=html_name, | |
396 DOM_NAME=dom_name, | |
397 TYPE=event_type) | |
398 | |
399 def EmitStreamGetters(self, interface, html_interface_name, custom_events, | |
400 members_emitter): | |
401 events = self._GetEvents(interface, html_interface_name, custom_events) | |
402 if not events: | |
403 return | |
404 | |
405 for event_info in events: | |
406 (dom_name, html_name, event_type) = event_info | |
407 getter_name = 'on%s%s' % (html_name[:1].upper(), html_name[1:]) | |
408 | |
409 members_emitter.Emit( | |
410 "\n" | |
411 " Stream<$TYPE> get $(NAME) => $PROVIDER.forTarget(this);\n", | |
Jennifer Messerly
2013/01/11 21:57:17
one concern here:
every time someone registers an
blois
2013/01/11 22:51:30
1. I believe that the Stream API is essentially im
| |
412 NAME=getter_name, | |
413 PROVIDER=html_name + 'Event', | |
414 TYPE=event_type) | |
415 | |
416 def _GetEvents(self, interface, html_interface_name, custom_events): | |
417 events = set([attr for attr in interface.attributes | |
418 if attr.type.id == 'EventListener']) | |
419 if not events and interface.id not in _html_explicit_event_classes: | |
420 return None | |
421 | |
422 dom_event_names = set() | |
423 for event in events: | |
424 dom_name = event.id[2:] | |
425 dom_name = _on_attribute_to_event_name_mapping.get(dom_name, dom_name) | |
426 dom_event_names.add(dom_name) | |
427 if html_interface_name in _html_manual_events: | |
428 dom_event_names.update(_html_manual_events[html_interface_name]) | |
429 | |
430 events = [] | |
431 for dom_name in sorted(dom_event_names): | |
432 event_info = self._FindEventInfo(html_interface_name, dom_name) | |
433 if not event_info: | |
434 continue | |
435 | |
436 (html_name, event_type) = event_info | |
437 full_event_name = '%sEvents.%s' % (html_interface_name, html_name) | |
438 if not full_event_name in custom_events: | |
439 events.append((dom_name, html_name, event_type)) | |
440 return events | |
441 | |
442 def _FindEventInfo(self, html_interface_name, dom_event_name): | |
443 key = '%s.%s' % (html_interface_name, dom_event_name) | |
444 if key in _html_event_types: | |
445 return _html_event_types[key] | |
446 key = '*.%s' % dom_event_name | |
447 if key in _html_event_types: | |
448 return _html_event_types[key] | |
449 _logger.warn('Cannot resolve event type for %s.%s' % | |
450 (html_interface_name, dom_event_name)) | |
451 return None | |
452 | |
198 def ProcessInterface(self, interface, html_interface_name, custom_events, | 453 def ProcessInterface(self, interface, html_interface_name, custom_events, |
199 events_implementation_emitter): | 454 events_implementation_emitter): |
200 event_names = set([attr.id[2:] for attr in interface.attributes | 455 event_names = set([attr.id[2:] for attr in interface.attributes |
201 if attr.type.id == 'EventListener']) | 456 if attr.type.id == 'EventListener']) |
202 | 457 |
203 # Document and DocumentFragment actually derive from Element, so omit | 458 # Document and DocumentFragment actually derive from Element, so omit |
204 # any events which are duplicated with that. | 459 # any events which are duplicated with that. |
205 if interface.id == 'Document' or interface.id == 'DocumentFragment': | 460 if interface.id == 'Document' or interface.id == 'DocumentFragment': |
206 element_interface = self._database.GetInterface('Element') | 461 element_interface = self._database.GetInterface('Element') |
207 for attr in element_interface.attributes: | 462 for attr in element_interface.attributes: |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
267 parent_events_class_name = 'Events' | 522 parent_events_class_name = 'Events' |
268 interfaces_with_events = set() | 523 interfaces_with_events = set() |
269 for parent in self._database.Hierarchy(interface): | 524 for parent in self._database.Hierarchy(interface): |
270 if parent != interface and parent.id in self._event_classes: | 525 if parent != interface and parent.id in self._event_classes: |
271 parent_name = self._renamer.RenameInterface(parent) | 526 parent_name = self._renamer.RenameInterface(parent) |
272 parent_events_class_name = parent_name + 'Events' | 527 parent_events_class_name = parent_name + 'Events' |
273 interfaces_with_events.add(parent) | 528 interfaces_with_events.add(parent) |
274 if len(interfaces_with_events) > 1: | 529 if len(interfaces_with_events) > 1: |
275 raise Exception('Only one parent event class allowed ' + interface.id) | 530 raise Exception('Only one parent event class allowed ' + interface.id) |
276 return parent_events_class_name | 531 return parent_events_class_name |
OLD | NEW |