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:html'; | 8 import 'dart:html'; |
9 import 'dart:convert'; | 9 import 'dart:convert'; |
10 import 'package:observatory/service.dart' as S; | 10 import 'package:observatory/service.dart' as S; |
11 import 'package:observatory/service_html.dart' as SH; | 11 import 'package:observatory/service_html.dart' as SH; |
12 import 'package:observatory/models.dart' as M; | 12 import 'package:observatory/models.dart' as M; |
13 import 'package:observatory/src/elements/helpers/nav_bar.dart'; | 13 import 'package:observatory/src/elements/helpers/nav_bar.dart'; |
14 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; | 14 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; |
15 import 'package:observatory/src/elements/helpers/tag.dart'; | 15 import 'package:observatory/src/elements/helpers/tag.dart'; |
16 import 'package:observatory/src/elements/nav/notify.dart'; | 16 import 'package:observatory/src/elements/nav/notify.dart'; |
17 import 'package:observatory/src/elements/nav/refresh.dart'; | 17 import 'package:observatory/src/elements/nav/refresh.dart'; |
18 import 'package:observatory/src/elements/nav/top_menu.dart'; | 18 import 'package:observatory/src/elements/nav/top_menu.dart'; |
19 import 'package:observatory/src/elements/nav/vm_menu.dart'; | 19 import 'package:observatory/src/elements/nav/vm_menu.dart'; |
20 | 20 |
21 enum _Profile { | 21 enum _Profile { none, dart, vm, all, custom } |
22 none, | |
23 dart, | |
24 vm, | |
25 all, | |
26 custom | |
27 } | |
28 | 22 |
29 class TimelinePageElement extends HtmlElement implements Renderable { | 23 class TimelinePageElement extends HtmlElement implements Renderable { |
30 static const tag = const Tag<TimelinePageElement>('timeline-page', | 24 static const tag = |
31 dependencies: const [ | 25 const Tag<TimelinePageElement>('timeline-page', dependencies: const [ |
32 NavTopMenuElement.tag, | 26 NavTopMenuElement.tag, |
33 NavVMMenuElement.tag, | 27 NavVMMenuElement.tag, |
34 NavRefreshElement.tag, | 28 NavRefreshElement.tag, |
35 NavNotifyElement.tag | 29 NavNotifyElement.tag |
36 ]); | 30 ]); |
37 | 31 |
38 RenderingScheduler<TimelinePageElement> _r; | 32 RenderingScheduler<TimelinePageElement> _r; |
39 | 33 |
40 Stream<RenderedEvent<TimelinePageElement>> get onRendered => _r.onRendered; | 34 Stream<RenderedEvent<TimelinePageElement>> get onRendered => _r.onRendered; |
41 | 35 |
42 M.VM _vm; | 36 M.VM _vm; |
43 M.EventRepository _events; | 37 M.EventRepository _events; |
44 M.NotificationRepository _notifications; | 38 M.NotificationRepository _notifications; |
45 String _recorderName = ''; | 39 String _recorderName = ''; |
46 _Profile _profile = _Profile.none; | 40 _Profile _profile = _Profile.none; |
47 final Set<String> _availableStreams = new Set<String>(); | 41 final Set<String> _availableStreams = new Set<String>(); |
48 final Set<String> _recordedStreams = new Set<String>(); | 42 final Set<String> _recordedStreams = new Set<String>(); |
49 | 43 |
50 M.VMRef get vm => _vm; | 44 M.VMRef get vm => _vm; |
51 M.NotificationRepository get notifications => _notifications; | 45 M.NotificationRepository get notifications => _notifications; |
52 | 46 |
53 factory TimelinePageElement(M.VM vm, M.EventRepository events, | 47 factory TimelinePageElement( |
54 M.NotificationRepository notifications, | 48 M.VM vm, M.EventRepository events, M.NotificationRepository notifications, |
55 {RenderingQueue queue}) { | 49 {RenderingQueue queue}) { |
56 assert(vm != null); | 50 assert(vm != null); |
57 assert(events != null); | 51 assert(events != null); |
58 assert(notifications != null); | 52 assert(notifications != null); |
59 TimelinePageElement e = document.createElement(tag.name); | 53 TimelinePageElement e = document.createElement(tag.name); |
60 e._r = new RenderingScheduler(e, queue: queue); | 54 e._r = new RenderingScheduler(e, queue: queue); |
61 e._vm = vm; | 55 e._vm = vm; |
62 e._events = events; | 56 e._events = events; |
63 e._notifications = notifications; | 57 e._notifications = notifications; |
64 return e; | 58 return e; |
65 } | 59 } |
66 | 60 |
67 TimelinePageElement.created() : super.created(); | 61 TimelinePageElement.created() : super.created(); |
68 | 62 |
69 @override | 63 @override |
70 attached() { | 64 attached() { |
71 super.attached(); | 65 super.attached(); |
72 _r.enable(); | 66 _r.enable(); |
73 _setupInitialState(); | 67 _setupInitialState(); |
74 } | 68 } |
75 | 69 |
76 @override | 70 @override |
77 detached() { | 71 detached() { |
78 super.detached(); | 72 super.detached(); |
79 _r.disable(notify: true); | 73 _r.disable(notify: true); |
80 children = []; | 74 children = []; |
81 } | 75 } |
82 | 76 |
83 IFrameElement _frame; | 77 IFrameElement _frame; |
84 DivElement _content; | 78 DivElement _content; |
85 | 79 |
86 void render() { | 80 void render() { |
87 if (_frame == null) { | 81 if (_frame == null) { |
88 _frame = new IFrameElement()..src = 'timeline.html'; | 82 _frame = new IFrameElement()..src = 'timeline.html'; |
89 } | 83 } |
90 if (_content == null) { | 84 if (_content == null) { |
91 _content = new DivElement()..classes = ['content-centered-big']; | 85 _content = new DivElement()..classes = ['content-centered-big']; |
92 } | 86 } |
93 _content.children = [ | 87 _content.children = [ |
94 new HeadingElement.h1()..text = 'Timeline settings', | 88 new HeadingElement.h1()..text = 'Timeline settings', |
95 new DivElement()..classes = ['memberList'] | 89 new DivElement() |
| 90 ..classes = ['memberList'] |
96 ..children = [ | 91 ..children = [ |
97 new DivElement()..classes = ['memberItem'] | 92 new DivElement() |
| 93 ..classes = ['memberItem'] |
98 ..children = [ | 94 ..children = [ |
99 new DivElement()..classes = ['memberName'] | 95 new DivElement() |
| 96 ..classes = ['memberName'] |
100 ..text = 'Recorder:', | 97 ..text = 'Recorder:', |
101 new DivElement()..classes = ['memberValue'] | 98 new DivElement() |
| 99 ..classes = ['memberValue'] |
102 ..text = _recorderName | 100 ..text = _recorderName |
103 ], | 101 ], |
104 new DivElement()..classes = ['memberItem'] | 102 new DivElement() |
| 103 ..classes = ['memberItem'] |
105 ..children = [ | 104 ..children = [ |
106 new DivElement()..classes = ['memberName'] | 105 new DivElement() |
| 106 ..classes = ['memberName'] |
107 ..text = 'Recorded Streams Profile:', | 107 ..text = 'Recorded Streams Profile:', |
108 new DivElement()..classes = ['memberValue'] | 108 new DivElement() |
| 109 ..classes = ['memberValue'] |
109 ..children = _createProfileSelect() | 110 ..children = _createProfileSelect() |
110 ], | 111 ], |
111 new DivElement()..classes = ['memberItem'] | 112 new DivElement() |
| 113 ..classes = ['memberItem'] |
112 ..children = [ | 114 ..children = [ |
113 new DivElement()..classes = ['memberName'] | 115 new DivElement() |
| 116 ..classes = ['memberName'] |
114 ..text = 'Recorded Streams:', | 117 ..text = 'Recorded Streams:', |
115 new DivElement()..classes = ['memberValue'] | 118 new DivElement() |
116 ..children = | 119 ..classes = ['memberValue'] |
117 _availableStreams.map(_makeStreamToggle).toList() | 120 ..children = _availableStreams.map(_makeStreamToggle).toList() |
118 ] | 121 ] |
119 ] | 122 ] |
120 ]; | 123 ]; |
121 if (children.isEmpty) { | 124 if (children.isEmpty) { |
122 children = [ | 125 children = [ |
123 navBar([ | 126 navBar([ |
124 new NavTopMenuElement(queue: _r.queue), | 127 new NavTopMenuElement(queue: _r.queue), |
125 new NavVMMenuElement(_vm, _events, queue: _r.queue), | 128 new NavVMMenuElement(_vm, _events, queue: _r.queue), |
126 new NavRefreshElement(queue: _r.queue) | 129 new NavRefreshElement(queue: _r.queue) |
127 ..onRefresh.listen((e) async { | 130 ..onRefresh.listen((e) async { |
128 e.element.disabled = true; | 131 e.element.disabled = true; |
129 await _refresh(); | 132 await _refresh(); |
130 e.element.disabled = false; | 133 e.element.disabled = false; |
131 }), | 134 }), |
132 new NavRefreshElement(label: 'clear', queue: _r.queue) | 135 new NavRefreshElement(label: 'clear', queue: _r.queue) |
133 ..onRefresh.listen((e) async { | 136 ..onRefresh.listen((e) async { |
134 e.element.disabled = true; | 137 e.element.disabled = true; |
135 await _clear(); | 138 await _clear(); |
136 e.element.disabled = false; | 139 e.element.disabled = false; |
137 }), | 140 }), |
138 new NavRefreshElement(label: 'save', queue: _r.queue) | 141 new NavRefreshElement(label: 'save', queue: _r.queue) |
139 ..onRefresh.listen((e) async { | 142 ..onRefresh.listen((e) async { |
140 e.element.disabled = true; | 143 e.element.disabled = true; |
141 await _save(); | 144 await _save(); |
142 e.element.disabled = false; | 145 e.element.disabled = false; |
143 }), | 146 }), |
144 new NavRefreshElement(label: 'load', queue: _r.queue) | 147 new NavRefreshElement(label: 'load', queue: _r.queue) |
145 ..onRefresh.listen((e) async { | 148 ..onRefresh.listen((e) async { |
146 e.element.disabled = true; | 149 e.element.disabled = true; |
147 await _load(); | 150 await _load(); |
148 e.element.disabled = false; | 151 e.element.disabled = false; |
149 }), | 152 }), |
150 new NavNotifyElement(_notifications, queue: _r.queue) | 153 new NavNotifyElement(_notifications, queue: _r.queue) |
151 ]), | 154 ]), |
152 _content, | 155 _content, |
153 new DivElement()..classes = ['iframe'] | 156 new DivElement() |
154 ..children = [ | 157 ..classes = ['iframe'] |
155 _frame | 158 ..children = [_frame] |
156 ] | |
157 ]; | 159 ]; |
158 } | 160 } |
159 } | 161 } |
160 | 162 |
161 List<Element> _createProfileSelect() { | 163 List<Element> _createProfileSelect() { |
162 var s; | 164 var s; |
163 return [ | 165 return [ |
164 s = new SelectElement()..classes = ['direction-select'] | 166 s = new SelectElement() |
| 167 ..classes = ['direction-select'] |
165 ..value = _profileToString(_profile) | 168 ..value = _profileToString(_profile) |
166 ..children = _Profile.values.map((direction) { | 169 ..children = _Profile.values.map((direction) { |
167 return new OptionElement(value: _profileToString(direction), | 170 return new OptionElement( |
168 selected: _profile == direction) | 171 value: _profileToString(direction), |
169 ..text = _profileToString(direction); | 172 selected: _profile == direction) |
170 }).toList(growable: false) | 173 ..text = _profileToString(direction); |
| 174 }).toList(growable: false) |
171 ..onChange.listen((_) { | 175 ..onChange.listen((_) { |
172 _profile = _Profile.values[s.selectedIndex]; | 176 _profile = _Profile.values[s.selectedIndex]; |
173 _applyPreset(); | 177 _applyPreset(); |
174 _r.dirty(); | 178 _r.dirty(); |
175 }) | 179 }) |
176 ]; | 180 ]; |
177 } | 181 } |
178 | 182 |
179 String _profileToString(_Profile profile) { | 183 String _profileToString(_Profile profile) { |
180 switch (profile) { | 184 switch (profile) { |
181 case _Profile.none: return 'none'; | 185 case _Profile.none: |
182 case _Profile.dart: return 'Dart Developer'; | 186 return 'none'; |
183 case _Profile.vm: return 'VM Developer'; | 187 case _Profile.dart: |
184 case _Profile.all: return 'All'; | 188 return 'Dart Developer'; |
185 case _Profile.custom: return 'Custom'; | 189 case _Profile.vm: |
| 190 return 'VM Developer'; |
| 191 case _Profile.all: |
| 192 return 'All'; |
| 193 case _Profile.custom: |
| 194 return 'Custom'; |
186 } | 195 } |
187 throw new Exception('Unkown Profile ${profile}'); | 196 throw new Exception('Unkown Profile ${profile}'); |
188 } | 197 } |
189 | 198 |
190 Future _refresh() async { | 199 Future _refresh() async { |
191 S.VM vm = _vm as S.VM; | 200 S.VM vm = _vm as S.VM; |
192 await vm.reload(); | 201 await vm.reload(); |
193 await vm.reloadIsolates(); | 202 await vm.reloadIsolates(); |
194 return _postMessage('refresh'); | 203 return _postMessage('refresh'); |
195 } | 204 } |
(...skipping 18 matching lines...) Expand all Loading... |
214 for (var isolate in vm.isolates) { | 223 for (var isolate in vm.isolates) { |
215 isolateIds.add(isolate.id); | 224 isolateIds.add(isolate.id); |
216 } | 225 } |
217 var message = { | 226 var message = { |
218 'method': method, | 227 'method': method, |
219 'params': { | 228 'params': { |
220 'vmAddress': (vm as SH.WebSocketVM).target.networkAddress, | 229 'vmAddress': (vm as SH.WebSocketVM).target.networkAddress, |
221 'isolateIds': isolateIds | 230 'isolateIds': isolateIds |
222 } | 231 } |
223 }; | 232 }; |
224 _frame.contentWindow.postMessage(JSON.encode(message), window.location.href)
; | 233 _frame.contentWindow |
| 234 .postMessage(JSON.encode(message), window.location.href); |
225 return null; | 235 return null; |
226 } | 236 } |
227 | 237 |
228 Future _setupInitialState() async { | 238 Future _setupInitialState() async { |
229 await _updateRecorderUI(); | 239 await _updateRecorderUI(); |
230 await _refresh(); | 240 await _refresh(); |
231 } | 241 } |
232 | 242 |
233 // Dart developers care about the following streams: | 243 // Dart developers care about the following streams: |
234 List<String> _dartPreset = | 244 List<String> _dartPreset = ['GC', 'Compiler', 'Dart']; |
235 ['GC', 'Compiler', 'Dart']; | |
236 | 245 |
237 // VM developers care about the following streams: | 246 // VM developers care about the following streams: |
238 List<String> _vmPreset = | 247 List<String> _vmPreset = [ |
239 ['GC', 'Compiler', 'Dart', 'Debugger', 'Embedder', 'Isolate', 'VM']; | 248 'GC', |
| 249 'Compiler', |
| 250 'Dart', |
| 251 'Debugger', |
| 252 'Embedder', |
| 253 'Isolate', |
| 254 'VM' |
| 255 ]; |
240 | 256 |
241 void _applyPreset() { | 257 void _applyPreset() { |
242 switch (_profile) { | 258 switch (_profile) { |
243 case _Profile.none: | 259 case _Profile.none: |
244 _recordedStreams.clear(); | 260 _recordedStreams.clear(); |
245 break; | 261 break; |
246 case _Profile.all: | 262 case _Profile.all: |
247 _recordedStreams.clear(); | 263 _recordedStreams.clear(); |
248 _recordedStreams.addAll(_availableStreams); | 264 _recordedStreams.addAll(_availableStreams); |
249 break; | 265 break; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 return vm.invokeRpc('_setVMTimelineFlags', { | 316 return vm.invokeRpc('_setVMTimelineFlags', { |
301 'recordedStreams': '[${_recordedStreams.join(', ')}]', | 317 'recordedStreams': '[${_recordedStreams.join(', ')}]', |
302 }); | 318 }); |
303 } | 319 } |
304 | 320 |
305 void _processFlags(S.ServiceMap response) { | 321 void _processFlags(S.ServiceMap response) { |
306 // Grab the recorder name. | 322 // Grab the recorder name. |
307 _recorderName = response['recorderName']; | 323 _recorderName = response['recorderName']; |
308 // Update the set of available streams. | 324 // Update the set of available streams. |
309 _availableStreams.clear(); | 325 _availableStreams.clear(); |
310 response['availableStreams'].forEach( | 326 response['availableStreams'] |
311 (String streamName) => _availableStreams.add(streamName)); | 327 .forEach((String streamName) => _availableStreams.add(streamName)); |
312 // Update the set of recorded streams. | 328 // Update the set of recorded streams. |
313 _recordedStreams.clear(); | 329 _recordedStreams.clear(); |
314 response['recordedStreams'].forEach( | 330 response['recordedStreams'] |
315 (String streamName) => _recordedStreams.add(streamName)); | 331 .forEach((String streamName) => _recordedStreams.add(streamName)); |
316 _r.dirty(); | 332 _r.dirty(); |
317 } | 333 } |
318 } | 334 } |
OLD | NEW |