Chromium Code Reviews| Index: runtime/observatory/lib/src/elements/class_tree.dart |
| diff --git a/runtime/observatory/lib/src/elements/class_tree.dart b/runtime/observatory/lib/src/elements/class_tree.dart |
| index 16f6928fbd72a7b193f0445f2b021e5909b929b9..cb927b272e16b5aa9106a0093ab1035e36f64d92 100644 |
| --- a/runtime/observatory/lib/src/elements/class_tree.dart |
| +++ b/runtime/observatory/lib/src/elements/class_tree.dart |
| @@ -4,14 +4,193 @@ |
| library class_tree_element; |
| -import 'observatory_element.dart'; |
| -import 'dart:async'; |
| import 'dart:html'; |
| -import 'package:logging/logging.dart'; |
| -import 'package:observatory/app.dart'; |
| -import 'package:observatory/service.dart'; |
| -import 'package:polymer/polymer.dart'; |
| +import 'dart:async'; |
| +import 'package:observatory/models.dart' as M; |
| +import 'package:observatory/src/elements/class_ref.dart'; |
| +import 'package:observatory/src/elements/containers/virtual_tree.dart'; |
| +import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; |
| +import 'package:observatory/src/elements/helpers/tag.dart'; |
| +import 'package:observatory/src/elements/helpers/uris.dart'; |
| +import 'package:observatory/src/elements/nav/bar.dart'; |
| +import 'package:observatory/src/elements/nav/isolate_menu.dart'; |
| +import 'package:observatory/src/elements/nav/menu.dart'; |
| +import 'package:observatory/src/elements/nav/notify.dart'; |
| +import 'package:observatory/src/elements/nav/top_menu.dart'; |
| +import 'package:observatory/src/elements/nav/vm_menu.dart'; |
| + |
| + |
| +class ClassTreeElement extends HtmlElement implements Renderable{ |
| + static const tag = const Tag<ClassTreeElement>('class-tree', |
| + dependencies: const [ClassRefElement.tag, |
| + NavBarElement.tag, |
| + NavIsolateMenuElement.tag, |
| + NavMenuElement.tag, |
| + NavNotifyElement.tag, |
| + NavTopMenuElement.tag, |
| + NavVMMenuElement.tag]); |
| + |
| + RenderingScheduler _r; |
| + |
| + Stream<RenderedEvent<ClassTreeElement>> get onRendered => _r.onRendered; |
| + |
| + M.VMRef _vm; |
| + M.IsolateRef _isolate; |
| + M.EventRepository _events; |
| + M.NotificationRepository _notifications; |
| + M.ClassRepository _classes; |
| + M.InstanceRepository _instances; |
| + M.Class _object; |
| + final _subclasses = <String, Iterable<M.Class>>{}; |
| + final _mixins = <String, List<M.Class>>{}; |
| + |
| + factory ClassTreeElement(M.VMRef vm, M.IsolateRef isolate, |
| + M.EventRepository events, |
| + M.NotificationRepository notifications, |
| + M.ClassRepository classes, |
| + M.InstanceRepository instances, |
| + {RenderingQueue queue}) { |
| + assert(vm != null); |
| + assert(isolate != null); |
| + assert(events != null); |
| + assert(notifications != null); |
| + assert(classes != null); |
| + assert(instances != null); |
| + ClassTreeElement e = document.createElement(tag.name); |
| + e._r = new RenderingScheduler(e, queue: queue); |
| + e._vm = vm; |
| + e._isolate = isolate; |
| + e._events = events; |
| + e._notifications = notifications; |
| + e._classes = classes; |
| + e._instances = instances; |
| + return e; |
| + } |
| + |
| + ClassTreeElement.created() : super.created(); |
| + |
| + @override |
| + void attached() { |
| + super.attached(); |
| + _refresh(); |
| + _r.enable(); |
| + } |
| + |
| + @override |
| + void detached() { |
| + super.detached(); |
| + children = []; |
| + _r.disable(notify: true); |
| + } |
| + |
| + VirtualTreeElement _tree; |
| + |
| + void render() { |
| + children = [ |
| + new NavBarElement(queue: _r.queue) |
| + ..children = [ |
| + new NavTopMenuElement(queue: _r.queue), |
| + new NavVMMenuElement(_vm, _events, queue: _r.queue), |
| + new NavIsolateMenuElement(_isolate, _events, queue: _r.queue), |
| + new NavMenuElement('class hierarchy', link: Uris.classTree(_isolate), |
| + last: true, queue: _r.queue), |
| + new NavNotifyElement(_notifications, queue: _r.queue) |
| + ], |
| + new DivElement() |
| + ..classes = ['content-centered'] |
| + ..children = [ |
| + new HeadingElement.h1()..text = 'Class Hierarchy', |
| + new BRElement(), new HRElement(), |
| + _object == null ? (new HeadingElement.h2()..text = 'Loading...') |
| + : _createTree() |
| + ] |
| + ]; |
| + } |
| + |
| + Element _createTree() { |
| + _tree = new VirtualTreeElement(_create, _update, _children, |
| + items: [_object], queue: _r.queue); |
| + _tree.expand(_object, autoExpandWholeTree: true); |
| + return _tree; |
| + } |
| + |
| + Future _refresh() async { |
| + _object = null; |
| + _subclasses.clear(); |
| + _mixins.clear(); |
| + _object = await _register(await _classes.getObject()); |
| + _r.dirty(); |
| + } |
| + Future<M.Class> _register(M.Class cls) async { |
| + _subclasses[cls.id] = await Future.wait( |
| + (await Future.wait(cls.subclasses.map(_getActualChildrens))) |
| + .expand((f) => f) |
| + .map(_register) |
| + ); |
| + return cls; |
| + } |
| + |
| + Future<Iterable<M.Class>> _getActualChildrens(M.ClassRef ref) async { |
| + var cls = await _classes.get(ref.id); |
| + if (cls.isPatch) { |
| + return const []; |
| + } |
| + if (cls.mixin == null) { |
| + return [cls]; |
| + } |
| + var mixin = await _instances.get(cls.mixin.id); |
| + return (await Future.wait(cls.subclasses.map(_getActualChildrens))) |
| + .expand((f) => f) |
| + ..forEach((subcls) { |
| + // non canonical type. |
| + if (mixin.typeClass == null) { |
| + return; |
| + } |
| + _mixins[subcls.id] = (_mixins[subcls.id] ?? [])..add(mixin.typeClass); |
| + }); |
| + } |
| + |
| + static Element _create(toggle) { |
| + return new DivElement()..classes = ['class-tree-item'] |
| + ..children = [ |
| + new SpanElement()..classes = ['lines'], |
| + new SpanElement()..classes = ['expander'] |
| + ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)), |
| + new SpanElement()..classes = ['name'] |
| + ]; |
| + } |
| + |
| + void _update(HtmlElement el, M.Class cls, int index) { |
| + virtualTreeUpdateLines(el.children[0], index); |
| + if (cls.subclasses.isEmpty) { |
| + el.children[1].text = ''; |
| + } else { |
| + el.children[1].text = _tree.isExpanded(cls) ? '▼' : '►'; |
| + } |
| + el.children[2].children = [ |
| + new ClassRefElement(_isolate, cls, queue: _r.queue) |
| + ]; |
| + if (_mixins[cls.id] != null) { |
| + el.children[2].children.addAll(_createMixins(_mixins[cls.id])); |
| + } |
| + } |
| + |
| + List<Element> _createMixins(List<M.Class> classes) { |
| + final children = classes.expand((cls) => [ |
| + new SpanElement()..text = ', ', |
| + new ClassRefElement(_isolate, cls, queue: _r.queue) |
| + ]).toList(); |
| + children.first.text = ' width '; |
| + return children; |
| + } |
| + |
| + Iterable<M.Class> _children(M.Class cls) { |
| + return _subclasses[cls.id]; |
| + } |
| +} |
| + |
| +/* |
|
Cutch
2016/08/05 13:23:18
remove deleted code
cbernaschina
2016/08/05 17:16:46
Done.
|
| class ClassTreeRow extends TableTreeRow { |
| @reflectable final Isolate isolate; |
| @reflectable final Class cls; |
| @@ -151,3 +330,45 @@ class ClassTreeElement extends ObservatoryElement { |
| notifyPropertyChange(#tree, null, tree); |
| } |
| } |
| +*/ |
| + |
| +/* |
| +<polymer-element name="class-tree"> |
| + <template> |
| + <link rel="stylesheet" href="css/shared.css"> |
| + <style> |
| + .table { |
| + border-spacing: 0px; |
| + width: 100%; |
| + margin-bottom: 20px |
| + vertical-align: middle; |
| + } |
| + |
| + tr { |
| + background-color: #FFFFFF; |
| + } |
| + |
| + tr:hover { |
| + background-color: #FAFAFA; |
| + } |
| + |
| + th { |
| + text-align: left; |
| + } |
| + </style> |
| + <nav-bar> |
| + <top-nav-menu></top-nav-menu> |
| + <vm-nav-menu vm="{{ isolate.vm }}"></vm-nav-menu> |
| + <isolate-nav-menu isolate="{{ isolate }}"></isolate-nav-menu> |
| + <nav-menu link="{{ makeLink('/class-tree', isolate) }}" anchor="class hierarchy" last="{{ true }}"></nav-menu> |
| + <nav-notify notifications="{{ app.notifications }}"></nav-notify> |
| + </nav-bar> |
| + <div class="content-centered"> |
| + <h1>Class Hierarchy</h1> |
| + <table id="tableTree" class="table"> |
| + <tbody id="tableTreeBody"></tbody> |
| + </table> |
| + </div> |
| + </template> |
| +</polymer-element> |
| + */ |