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

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

Issue 2212253002: Converted Observatory class-tree element (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Removed tmp code Created 4 years, 4 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
OLDNEW
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 14 import 'package:observatory/src/elements/helpers/uris.dart';
15 class ClassTreeRow extends TableTreeRow { 15 import 'package:observatory/src/elements/nav/bar.dart';
16 @reflectable final Isolate isolate; 16 import 'package:observatory/src/elements/nav/isolate_menu.dart';
17 @reflectable final Class cls; 17 import 'package:observatory/src/elements/nav/menu.dart';
18 ClassTreeRow(this.isolate, this.cls, TableTree tree, ClassTreeRow parent) 18 import 'package:observatory/src/elements/nav/notify.dart';
19 : super(tree, parent) { 19 import 'package:observatory/src/elements/nav/top_menu.dart';
20 assert(isolate != null); 20 import 'package:observatory/src/elements/nav/vm_menu.dart';
21 assert(cls != null);
22 }
23
24 void _addChildren(List<Class> subclasses) {
25 for (var subclass in subclasses) {
26 if (subclass.isPatch) {
27 continue;
28 }
29 if (subclass.mixin != null) {
30 _addChildren(subclass.subclasses);
31 } else {
32 var row = new ClassTreeRow(isolate, subclass, tree, this);
33 children.add(row);
34 }
35 }
36 }
37
38 Future _addMixins(Class cls) async {
39 var classCell = flexColumns[0];
40 if (cls.superclass == null) {
41 return;
42 }
43 bool first = true;
44 while (cls.superclass != null && cls.superclass.mixin != null) {
45 cls = cls.superclass;
46 await cls.mixin.load();
47 var span = new SpanElement();
48 span.style.alignSelf = 'center';
49 span.style.whiteSpace = 'pre';
50 if (first) {
51 span.text = ' with ';
52 } else {
53 span.text = ', ';
54 }
55 classCell.children.add(span);
56 var mixinRef = new Element.tag('class-ref');
57 mixinRef.ref = cls.mixin.typeClass;
58 mixinRef.style.alignSelf = 'center';
59 classCell.children.add(mixinRef);
60 first = false;
61 }
62 }
63
64 Future _addClass(Class cls) async {
65 var classCell = flexColumns[0];
66 classCell.style.justifyContent = 'flex-start';
67 var classRef = new Element.tag('class-ref');
68 classRef.ref = cls;
69 classRef.style.alignSelf = 'center';
70 classCell.children.add(classRef);
71 if (cls.superclass != null && cls.superclass.mixin != null) {
72 await _addMixins(cls);
73 }
74 if (cls.subclasses.isNotEmpty) {
75 var span = new SpanElement();
76 span.style.paddingLeft = '.5em';
77 span.style.alignSelf = 'center';
78 int subclassCount = _indirectSubclassCount(cls) - 1;
79 if (subclassCount > 1) {
80 span.text = '($subclassCount subclasses)';
81 } else {
82 span.text = '($subclassCount subclass)';
83 }
84 classCell.children.add(span);
85 }
86 }
87
88 void onShow() {
89 super.onShow();
90 if (children.length == 0) {
91 _addChildren(cls.subclasses);
92 }
93 _addClass(cls);
94 }
95
96 static int _indirectSubclassCount(var cls) {
97 int count = 0;
98 if (cls.mixin == null) {
99 // Don't count synthetic mixin classes in subclass count.
100 count++;
101 }
102 for (var subclass in cls.subclasses) {
103 count += _indirectSubclassCount(subclass);
104 }
105 return count;
106 }
107
108 bool hasChildren() {
109 return cls.subclasses.isNotEmpty;
110 }
111 }
112 21
113 22
114 @CustomTag('class-tree') 23 class ClassTreeElement extends HtmlElement implements Renderable{
115 class ClassTreeElement extends ObservatoryElement { 24 static const tag = const Tag<ClassTreeElement>('class-tree',
116 @observable Isolate isolate; 25 dependencies: const [ClassRefElement.tag,
26 NavBarElement.tag,
27 NavIsolateMenuElement.tag,
28 NavMenuElement.tag,
29 NavNotifyElement.tag,
30 NavTopMenuElement.tag,
31 NavVMMenuElement.tag,
32 VirtualTreeElement.tag]);
117 33
118 TableTree tree; 34 RenderingScheduler _r;
35
36 Stream<RenderedEvent<ClassTreeElement>> get onRendered => _r.onRendered;
37
38 M.VMRef _vm;
39 M.IsolateRef _isolate;
40 M.EventRepository _events;
41 M.NotificationRepository _notifications;
42 M.ClassRepository _classes;
43 M.Class _object;
44 final _subclasses = <String, Iterable<M.Class>>{};
45 final _mixins = <String, List<M.Instance>>{};
46
47 factory ClassTreeElement(M.VMRef vm, M.IsolateRef isolate,
48 M.EventRepository events,
49 M.NotificationRepository notifications,
50 M.ClassRepository classes,
51 {RenderingQueue queue}) {
52 assert(vm != null);
53 assert(isolate != null);
54 assert(events != null);
55 assert(notifications != null);
56 assert(classes != null);
57 ClassTreeElement e = document.createElement(tag.name);
58 e._r = new RenderingScheduler(e, queue: queue);
59 e._vm = vm;
60 e._isolate = isolate;
61 e._events = events;
62 e._notifications = notifications;
63 e._classes = classes;
64 return e;
65 }
119 66
120 ClassTreeElement.created() : super.created(); 67 ClassTreeElement.created() : super.created();
121 68
122 @override 69 @override
123 void attached() { 70 void attached() {
124 super.attached(); 71 super.attached();
125 var tableBody = shadowRoot.querySelector('#tableTreeBody'); 72 _refresh();
126 assert(tableBody != null); 73 _r.enable();
127 tree = new TableTree(tableBody, 1); 74 }
128 if (isolate != null) { 75
129 _update(isolate.objectClass); 76 @override
77 void detached() {
78 super.detached();
79 children = [];
80 _r.disable(notify: true);
81 }
82
83 VirtualTreeElement _tree;
84
85 void render() {
86 children = [
87 new NavBarElement(queue: _r.queue)
88 ..children = [
89 new NavTopMenuElement(queue: _r.queue),
90 new NavVMMenuElement(_vm, _events, queue: _r.queue),
91 new NavIsolateMenuElement(_isolate, _events, queue: _r.queue),
92 new NavMenuElement('class hierarchy', link: Uris.classTree(_isolate),
93 last: true, queue: _r.queue),
94 new NavNotifyElement(_notifications, queue: _r.queue)
95 ],
96 new DivElement()
97 ..classes = ['content-centered']
98 ..children = [
99 new HeadingElement.h1()..text = 'Class Hierarchy',
100 new BRElement(), new HRElement(),
101 _object == null ? (new HeadingElement.h2()..text = 'Loading...')
102 : _createTree()
103 ]
104 ];
105 }
106
107 Element _createTree() {
108 _tree = new VirtualTreeElement(_create, _update, _children,
109 items: [_object], queue: _r.queue);
110 _tree.expand(_object, autoExpandSingleChildNodes: true);
111 return _tree;
112 }
113
114 Future _refresh() async {
115 _object = null;
116 _subclasses.clear();
117 _mixins.clear();
118 _object = await _register(await _classes.getObject());
119 _r.dirty();
120 }
121
122 Future<M.Class> _register(M.Class cls) async {
123 _subclasses[cls.id] = await Future.wait(
124 (await Future.wait(cls.subclasses.map(_getActualChildrens)))
125 .expand((f) => f)
126 .map(_register)
127 );
128 return cls;
129 }
130
131 Future<Iterable<M.Class>> _getActualChildrens(M.ClassRef ref) async {
132 var cls = await _classes.get(ref.id);
133 if (cls.isPatch) {
134 return const [];
135 }
136 if (cls.mixin == null) {
137 return [cls];
138 }
139 return (await Future.wait(cls.subclasses.map(_getActualChildrens)))
140 .expand((f) => f)
141 ..forEach((subcls) {
142 _mixins[subcls.id] = (_mixins[subcls.id] ?? [])..add(cls.mixin);
143 });
144 }
145
146 static Element _create(toggle) {
147 return new DivElement()..classes = ['class-tree-item']
148 ..children = [
149 new SpanElement()..classes = ['lines'],
150 new SpanElement()..classes = ['expander']
151 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
152 new SpanElement()..classes = ['name']
153 ];
154 }
155
156 void _update(HtmlElement el, M.Class cls, int index) {
157 virtualTreeUpdateLines(el.children[0], index);
158 if (cls.subclasses.isEmpty) {
159 el.children[1].text = '';
160 } else {
161 el.children[1].text = _tree.isExpanded(cls) ? '▼' : '►';
162 }
163 el.children[2].children = [
164 new ClassRefElement(_isolate, cls, queue: _r.queue)
165 ];
166 if (_mixins[cls.id] != null) {
167 el.children[2].children.addAll(_createMixins(_mixins[cls.id]));
130 } 168 }
131 } 169 }
132 170
133 isolateChanged(oldValue) { 171 List<Element> _createMixins(List<M.Instance> types) {
134 isolate.getClassHierarchy().then((objectClass) { 172 final children = types.expand((type) => [
135 _update(objectClass); 173 new SpanElement()..text = ', ',
136 }); 174 type.typeClass == null
175 ? (new SpanElement()..text = type.name.split('<').first)
176 : new ClassRefElement(_isolate, type.typeClass, queue: _r.queue)
177 ]).toList();
178 children.first.text = ' with ';
179 return children;
137 } 180 }
138 181
139 void _update(Class root) { 182 Iterable<M.Class> _children(M.Class cls) {
140 try { 183 return _subclasses[cls.id];
141 var rootRow = new ClassTreeRow(isolate, root, tree, null);
142 rootRow.children.add(new ClassTreeRow(isolate, root, tree, rootRow));
143 tree.initialize(rootRow);
144 } catch (e, stackTrace) {
145 Logger.root.warning('_update', e, stackTrace);
146 }
147 // Check if we only have one node at the root and expand it.
148 if (tree.rows.length == 1) {
149 tree.toggle(tree.rows[0]);
150 }
151 notifyPropertyChange(#tree, null, tree);
152 } 184 }
153 } 185 }
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/app/page.dart ('k') | runtime/observatory/lib/src/elements/class_tree.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698