| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 timeline_page_element; | 5 library timeline_page_element; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 import 'dart:html'; | 9 import 'dart:html'; |
| 10 import 'observatory_element.dart'; | 10 import 'observatory_element.dart'; |
| 11 import 'package:observatory/elements.dart'; | 11 import 'package:observatory/elements.dart'; |
| 12 import 'package:observatory/service_html.dart'; | 12 import 'package:observatory/service_html.dart'; |
| 13 import 'package:polymer/polymer.dart'; | 13 import 'package:polymer/polymer.dart'; |
| 14 | 14 |
| 15 | 15 |
| 16 @CustomTag('timeline-page') | 16 @CustomTag('timeline-page') |
| 17 class TimelinePageElement extends ObservatoryElement { | 17 class TimelinePageElement extends ObservatoryElement { |
| 18 TimelinePageElement.created() : super.created(); | 18 TimelinePageElement.created() : super.created() { |
| 19 } |
| 19 | 20 |
| 20 attached() { | 21 attached() { |
| 21 super.attached(); | 22 super.attached(); |
| 22 _resizeSubscription = window.onResize.listen((_) => _updateSize()); | 23 _resizeSubscription = window.onResize.listen((_) => _updateSize()); |
| 23 _updateSize(); | 24 _updateSize(); |
| 24 // Click refresh button. | 25 _setupInitialState(); |
| 25 NavRefreshElement refreshButton = $['refresh']; | |
| 26 refreshButton.buttonClick(null, null, null); | |
| 27 } | 26 } |
| 28 | 27 |
| 29 detached() { | 28 detached() { |
| 30 super.detached(); | 29 super.detached(); |
| 31 if (_resizeSubscription != null) { | 30 if (_resizeSubscription != null) { |
| 32 _resizeSubscription.cancel(); | 31 _resizeSubscription.cancel(); |
| 33 } | 32 } |
| 34 } | 33 } |
| 35 | 34 |
| 36 Future postMessage(String method) { | 35 Future postMessage(String method) { |
| 37 IFrameElement e = $['root']; | 36 IFrameElement e = $['root']; |
| 38 var isolateIds = new List(); | 37 var isolateIds = new List(); |
| 39 for (var isolate in app.vm.isolates) { | 38 for (var isolate in app.vm.isolates) { |
| 40 isolateIds.add(isolate.id); | 39 isolateIds.add(isolate.id); |
| 41 } | 40 } |
| 42 var message = { | 41 var message = { |
| 43 'method': method, | 42 'method': method, |
| 44 'params': { | 43 'params': { |
| 45 'vmAddress': (app.vm as WebSocketVM).target.networkAddress, | 44 'vmAddress': (app.vm as WebSocketVM).target.networkAddress, |
| 46 'isolateIds': isolateIds | 45 'isolateIds': isolateIds |
| 47 } | 46 } |
| 48 }; | 47 }; |
| 49 e.contentWindow.postMessage(JSON.encode(message), window.location.href); | 48 e.contentWindow.postMessage(JSON.encode(message), window.location.href); |
| 50 return null; | 49 return null; |
| 51 } | 50 } |
| 52 | 51 |
| 52 void _processFlags(ServiceMap response) { |
| 53 // Grab the recorder name. |
| 54 recorderName = response['recorderName']; |
| 55 // Update the set of available streams. |
| 56 _availableStreams.clear(); |
| 57 response['availableStreams'].forEach( |
| 58 (String streamName) => _availableStreams.add(streamName)); |
| 59 // Update the set of recorded streams. |
| 60 _recordedStreams.clear(); |
| 61 response['recordedStreams'].forEach( |
| 62 (String streamName) => _recordedStreams.add(streamName)); |
| 63 } |
| 64 |
| 65 Future _applyStreamChanges() { |
| 66 return app.vm.invokeRpc('_setVMTimelineFlags', { |
| 67 'recordedStreams': '[${_recordedStreams.join(', ')}]', |
| 68 }); |
| 69 } |
| 70 |
| 71 HtmlElement _makeStreamToggle(String streamName) { |
| 72 LabelElement label = new LabelElement(); |
| 73 label.style.paddingLeft = '8px'; |
| 74 SpanElement span = new SpanElement(); |
| 75 span.text = streamName; |
| 76 InputElement checkbox = new InputElement(); |
| 77 checkbox.onChange.listen((_) { |
| 78 if (checkbox.checked) { |
| 79 _recordedStreams.add(streamName); |
| 80 } else { |
| 81 _recordedStreams.remove(streamName); |
| 82 } |
| 83 _applyStreamChanges(); |
| 84 _updateRecorderUI(); |
| 85 }); |
| 86 checkbox.type = 'checkbox'; |
| 87 checkbox.checked = _recordedStreams.contains(streamName); |
| 88 label.children.add(checkbox); |
| 89 label.children.add(span); |
| 90 return label; |
| 91 } |
| 92 |
| 93 void _refreshRecorderUI() { |
| 94 DivElement e = $['streamList']; |
| 95 e.children.clear(); |
| 96 |
| 97 for (String streamName in _availableStreams) { |
| 98 e.children.add(_makeStreamToggle(streamName)); |
| 99 } |
| 100 } |
| 101 |
| 102 Future _updateRecorderUI() async { |
| 103 // Grab the current timeline flags. |
| 104 ServiceMap response = await app.vm.invokeRpc('_getVMTimelineFlags', {}); |
| 105 assert(response['type'] == 'TimelineFlags'); |
| 106 // Process them so we know available streams. |
| 107 _processFlags(response); |
| 108 // Refresh the UI. |
| 109 _refreshRecorderUI(); |
| 110 } |
| 111 |
| 112 Future _setupInitialState() async { |
| 113 await _updateRecorderUI(); |
| 114 // Finally, trigger a reload so we start with the latest timeline. |
| 115 await refresh(); |
| 116 } |
| 117 |
| 53 Future refresh() async { | 118 Future refresh() async { |
| 54 await app.vm.reload(); | 119 await app.vm.reload(); |
| 55 await app.vm.reloadIsolates(); | 120 await app.vm.reloadIsolates(); |
| 56 return postMessage('refresh'); | 121 return postMessage('refresh'); |
| 57 } | 122 } |
| 58 | 123 |
| 59 Future clear() async { | 124 Future clear() async { |
| 60 await app.vm.invokeRpc('_clearVMTimeline', {}); | 125 await app.vm.invokeRpc('_clearVMTimeline', {}); |
| 61 return postMessage('clear'); | 126 return postMessage('clear'); |
| 62 } | 127 } |
| 63 | 128 |
| 64 Future recordOn() async { | |
| 65 return app.vm.invokeRpc('_setVMTimelineFlags', { | |
| 66 'recordedStreams': ['all'], | |
| 67 }); | |
| 68 } | |
| 69 | |
| 70 Future recordOff() async { | |
| 71 return app.vm.invokeRpc('_setVMTimelineFlags', { | |
| 72 'recordedStreams': [], | |
| 73 }); | |
| 74 } | |
| 75 | |
| 76 Future saveTimeline() async { | 129 Future saveTimeline() async { |
| 77 return postMessage('save'); | 130 return postMessage('save'); |
| 78 } | 131 } |
| 79 | 132 |
| 80 Future loadTimeline() async { | 133 Future loadTimeline() async { |
| 81 return postMessage('load'); | 134 return postMessage('load'); |
| 82 } | 135 } |
| 83 | 136 |
| 84 _updateSize() { | 137 _updateSize() { |
| 85 IFrameElement e = $['root']; | 138 IFrameElement e = $['root']; |
| 86 final totalHeight = window.innerHeight; | 139 final totalHeight = window.innerHeight; |
| 87 final top = e.offset.top; | 140 final top = e.offset.top; |
| 88 final bottomMargin = 32; | 141 final bottomMargin = 32; |
| 89 final mainHeight = totalHeight - top - bottomMargin; | 142 final mainHeight = totalHeight - top - bottomMargin; |
| 90 e.style.setProperty('height', '${mainHeight}px'); | 143 e.style.setProperty('height', '${mainHeight}px'); |
| 91 e.style.setProperty('width', '100%'); | 144 e.style.setProperty('width', '100%'); |
| 92 } | 145 } |
| 93 | 146 |
| 94 | 147 |
| 95 StreamSubscription _resizeSubscription; | 148 StreamSubscription _resizeSubscription; |
| 149 @observable String recorderName; |
| 150 final Set<String> _availableStreams = new Set<String>(); |
| 151 final Set<String> _recordedStreams = new Set<String>(); |
| 96 } | 152 } |
| OLD | NEW |