Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(733)

Side by Side Diff: runtime/observatory/lib/src/elements/timeline_page.dart

Issue 1972523003: Improve Observatory Timeline UI (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | runtime/observatory/lib/src/elements/timeline_page.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 }
OLDNEW
« no previous file with comments | « no previous file | runtime/observatory/lib/src/elements/timeline_page.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698