OLD | NEW |
---|---|
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 class_tree_element; | 5 library class_tree_element; |
6 | 6 |
7 import 'observatory_element.dart'; | 7 import 'dart:html'; |
8 import 'dart:async'; | 8 import 'dart:async'; |
9 import 'dart:html'; | 9 import 'package:observatory/models.dart' as M; |
10 import 'package:logging/logging.dart'; | 10 import 'package:observatory/src/elements/class_ref.dart'; |
11 import 'package:observatory/app.dart'; | 11 import 'package:observatory/src/elements/containers/virtual_tree.dart'; |
12 import 'package:observatory/service.dart'; | 12 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; |
13 import 'package:polymer/polymer.dart'; | 13 import 'package:observatory/src/elements/helpers/tag.dart'; |
14 import 'package:observatory/src/elements/helpers/uris.dart'; | |
15 import 'package:observatory/src/elements/nav/bar.dart'; | |
16 import 'package:observatory/src/elements/nav/isolate_menu.dart'; | |
17 import 'package:observatory/src/elements/nav/menu.dart'; | |
18 import 'package:observatory/src/elements/nav/notify.dart'; | |
19 import 'package:observatory/src/elements/nav/top_menu.dart'; | |
20 import 'package:observatory/src/elements/nav/vm_menu.dart'; | |
14 | 21 |
22 | |
23 class ClassTreeElement extends HtmlElement implements Renderable{ | |
24 static const tag = const Tag<ClassTreeElement>('class-tree', | |
25 dependencies: const [ClassRefElement.tag, | |
26 NavBarElement.tag, | |
27 NavIsolateMenuElement.tag, | |
28 NavMenuElement.tag, | |
29 NavNotifyElement.tag, | |
30 NavTopMenuElement.tag, | |
31 NavVMMenuElement.tag]); | |
32 | |
33 RenderingScheduler _r; | |
34 | |
35 Stream<RenderedEvent<ClassTreeElement>> get onRendered => _r.onRendered; | |
36 | |
37 M.VMRef _vm; | |
38 M.IsolateRef _isolate; | |
39 M.EventRepository _events; | |
40 M.NotificationRepository _notifications; | |
41 M.ClassRepository _classes; | |
42 M.InstanceRepository _instances; | |
43 M.Class _object; | |
44 final _subclasses = <String, Iterable<M.Class>>{}; | |
45 final _mixins = <String, List<M.Class>>{}; | |
46 | |
47 factory ClassTreeElement(M.VMRef vm, M.IsolateRef isolate, | |
48 M.EventRepository events, | |
49 M.NotificationRepository notifications, | |
50 M.ClassRepository classes, | |
51 M.InstanceRepository instances, | |
52 {RenderingQueue queue}) { | |
53 assert(vm != null); | |
54 assert(isolate != null); | |
55 assert(events != null); | |
56 assert(notifications != null); | |
57 assert(classes != null); | |
58 assert(instances != null); | |
59 ClassTreeElement e = document.createElement(tag.name); | |
60 e._r = new RenderingScheduler(e, queue: queue); | |
61 e._vm = vm; | |
62 e._isolate = isolate; | |
63 e._events = events; | |
64 e._notifications = notifications; | |
65 e._classes = classes; | |
66 e._instances = instances; | |
67 return e; | |
68 } | |
69 | |
70 ClassTreeElement.created() : super.created(); | |
71 | |
72 @override | |
73 void attached() { | |
74 super.attached(); | |
75 _refresh(); | |
76 _r.enable(); | |
77 } | |
78 | |
79 @override | |
80 void detached() { | |
81 super.detached(); | |
82 children = []; | |
83 _r.disable(notify: true); | |
84 } | |
85 | |
86 VirtualTreeElement _tree; | |
87 | |
88 void render() { | |
89 children = [ | |
90 new NavBarElement(queue: _r.queue) | |
91 ..children = [ | |
92 new NavTopMenuElement(queue: _r.queue), | |
93 new NavVMMenuElement(_vm, _events, queue: _r.queue), | |
94 new NavIsolateMenuElement(_isolate, _events, queue: _r.queue), | |
95 new NavMenuElement('class hierarchy', link: Uris.classTree(_isolate), | |
96 last: true, queue: _r.queue), | |
97 new NavNotifyElement(_notifications, queue: _r.queue) | |
98 ], | |
99 new DivElement() | |
100 ..classes = ['content-centered'] | |
101 ..children = [ | |
102 new HeadingElement.h1()..text = 'Class Hierarchy', | |
103 new BRElement(), new HRElement(), | |
104 _object == null ? (new HeadingElement.h2()..text = 'Loading...') | |
105 : _createTree() | |
106 ] | |
107 ]; | |
108 } | |
109 | |
110 Element _createTree() { | |
111 _tree = new VirtualTreeElement(_create, _update, _children, | |
112 items: [_object], queue: _r.queue); | |
113 _tree.expand(_object, autoExpandWholeTree: true); | |
114 return _tree; | |
115 } | |
116 | |
117 Future _refresh() async { | |
118 _object = null; | |
119 _subclasses.clear(); | |
120 _mixins.clear(); | |
121 _object = await _register(await _classes.getObject()); | |
122 _r.dirty(); | |
123 } | |
124 | |
125 Future<M.Class> _register(M.Class cls) async { | |
126 _subclasses[cls.id] = await Future.wait( | |
127 (await Future.wait(cls.subclasses.map(_getActualChildrens))) | |
128 .expand((f) => f) | |
129 .map(_register) | |
130 ); | |
131 return cls; | |
132 } | |
133 | |
134 Future<Iterable<M.Class>> _getActualChildrens(M.ClassRef ref) async { | |
135 var cls = await _classes.get(ref.id); | |
136 if (cls.isPatch) { | |
137 return const []; | |
138 } | |
139 if (cls.mixin == null) { | |
140 return [cls]; | |
141 } | |
142 var mixin = await _instances.get(cls.mixin.id); | |
143 return (await Future.wait(cls.subclasses.map(_getActualChildrens))) | |
144 .expand((f) => f) | |
145 ..forEach((subcls) { | |
146 // non canonical type. | |
147 if (mixin.typeClass == null) { | |
148 return; | |
149 } | |
150 _mixins[subcls.id] = (_mixins[subcls.id] ?? [])..add(mixin.typeClass); | |
151 }); | |
152 } | |
153 | |
154 static Element _create(toggle) { | |
155 return new DivElement()..classes = ['class-tree-item'] | |
156 ..children = [ | |
157 new SpanElement()..classes = ['lines'], | |
158 new SpanElement()..classes = ['expander'] | |
159 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)), | |
160 new SpanElement()..classes = ['name'] | |
161 ]; | |
162 } | |
163 | |
164 void _update(HtmlElement el, M.Class cls, int index) { | |
165 virtualTreeUpdateLines(el.children[0], index); | |
166 if (cls.subclasses.isEmpty) { | |
167 el.children[1].text = ''; | |
168 } else { | |
169 el.children[1].text = _tree.isExpanded(cls) ? '▼' : '►'; | |
170 } | |
171 el.children[2].children = [ | |
172 new ClassRefElement(_isolate, cls, queue: _r.queue) | |
173 ]; | |
174 if (_mixins[cls.id] != null) { | |
175 el.children[2].children.addAll(_createMixins(_mixins[cls.id])); | |
176 } | |
177 } | |
178 | |
179 List<Element> _createMixins(List<M.Class> classes) { | |
180 final children = classes.expand((cls) => [ | |
181 new SpanElement()..text = ', ', | |
182 new ClassRefElement(_isolate, cls, queue: _r.queue) | |
183 ]).toList(); | |
184 children.first.text = ' width '; | |
185 return children; | |
186 } | |
187 | |
188 Iterable<M.Class> _children(M.Class cls) { | |
189 return _subclasses[cls.id]; | |
190 } | |
191 } | |
192 | |
193 /* | |
Cutch
2016/08/05 13:23:18
remove deleted code
cbernaschina
2016/08/05 17:16:46
Done.
| |
15 class ClassTreeRow extends TableTreeRow { | 194 class ClassTreeRow extends TableTreeRow { |
16 @reflectable final Isolate isolate; | 195 @reflectable final Isolate isolate; |
17 @reflectable final Class cls; | 196 @reflectable final Class cls; |
18 ClassTreeRow(this.isolate, this.cls, TableTree tree, ClassTreeRow parent) | 197 ClassTreeRow(this.isolate, this.cls, TableTree tree, ClassTreeRow parent) |
19 : super(tree, parent) { | 198 : super(tree, parent) { |
20 assert(isolate != null); | 199 assert(isolate != null); |
21 assert(cls != null); | 200 assert(cls != null); |
22 } | 201 } |
23 | 202 |
24 void _addChildren(List<Class> subclasses) { | 203 void _addChildren(List<Class> subclasses) { |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
144 } catch (e, stackTrace) { | 323 } catch (e, stackTrace) { |
145 Logger.root.warning('_update', e, stackTrace); | 324 Logger.root.warning('_update', e, stackTrace); |
146 } | 325 } |
147 // Check if we only have one node at the root and expand it. | 326 // Check if we only have one node at the root and expand it. |
148 if (tree.rows.length == 1) { | 327 if (tree.rows.length == 1) { |
149 tree.toggle(tree.rows[0]); | 328 tree.toggle(tree.rows[0]); |
150 } | 329 } |
151 notifyPropertyChange(#tree, null, tree); | 330 notifyPropertyChange(#tree, null, tree); |
152 } | 331 } |
153 } | 332 } |
333 */ | |
334 | |
335 /* | |
336 <polymer-element name="class-tree"> | |
337 <template> | |
338 <link rel="stylesheet" href="css/shared.css"> | |
339 <style> | |
340 .table { | |
341 border-spacing: 0px; | |
342 width: 100%; | |
343 margin-bottom: 20px | |
344 vertical-align: middle; | |
345 } | |
346 | |
347 tr { | |
348 background-color: #FFFFFF; | |
349 } | |
350 | |
351 tr:hover { | |
352 background-color: #FAFAFA; | |
353 } | |
354 | |
355 th { | |
356 text-align: left; | |
357 } | |
358 </style> | |
359 <nav-bar> | |
360 <top-nav-menu></top-nav-menu> | |
361 <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu> | |
362 <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu> | |
363 <nav-menu link="{{ makeLink('/class-tree', isolate) }}" anchor="class hier archy" last="{{ true }}"></nav-menu> | |
364 <nav-notify notifications="{{ app.notifications }}"></nav-notify> | |
365 </nav-bar> | |
366 <div class="content-centered"> | |
367 <h1>Class Hierarchy</h1> | |
368 <table id="tableTree" class="table"> | |
369 <tbody id="tableTreeBody"></tbody> | |
370 </table> | |
371 </div> | |
372 </template> | |
373 </polymer-element> | |
374 */ | |
OLD | NEW |