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 'dart:html'; | 7 import 'dart:html'; |
8 import 'dart:async'; | 8 import 'dart:async'; |
9 import 'package:observatory/models.dart' as M; | 9 import 'package:observatory/models.dart' as M; |
10 import 'package:observatory/src/elements/class_ref.dart'; | 10 import 'package:observatory/src/elements/class_ref.dart'; |
11 import 'package:observatory/src/elements/containers/virtual_tree.dart'; | 11 import 'package:observatory/src/elements/containers/virtual_tree.dart'; |
12 import 'package:observatory/src/elements/helpers/nav_bar.dart'; | 12 import 'package:observatory/src/elements/helpers/nav_bar.dart'; |
13 import 'package:observatory/src/elements/helpers/nav_menu.dart'; | 13 import 'package:observatory/src/elements/helpers/nav_menu.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/isolate_menu.dart'; | 16 import 'package:observatory/src/elements/nav/isolate_menu.dart'; |
17 import 'package:observatory/src/elements/nav/notify.dart'; | 17 import 'package:observatory/src/elements/nav/notify.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 | 21 class ClassTreeElement extends HtmlElement implements Renderable { |
22 class ClassTreeElement extends HtmlElement implements Renderable{ | 22 static const tag = |
23 static const tag = const Tag<ClassTreeElement>('class-tree', | 23 const Tag<ClassTreeElement>('class-tree', dependencies: const [ |
24 dependencies: const [ClassRefElement.tag, | 24 ClassRefElement.tag, |
25 NavIsolateMenuElement.tag, | 25 NavIsolateMenuElement.tag, |
26 NavNotifyElement.tag, | 26 NavNotifyElement.tag, |
27 NavTopMenuElement.tag, | 27 NavTopMenuElement.tag, |
28 NavVMMenuElement.tag, | 28 NavVMMenuElement.tag, |
29 VirtualTreeElement.tag]); | 29 VirtualTreeElement.tag |
| 30 ]); |
30 | 31 |
31 RenderingScheduler _r; | 32 RenderingScheduler _r; |
32 | 33 |
33 Stream<RenderedEvent<ClassTreeElement>> get onRendered => _r.onRendered; | 34 Stream<RenderedEvent<ClassTreeElement>> get onRendered => _r.onRendered; |
34 | 35 |
35 M.VMRef _vm; | 36 M.VMRef _vm; |
36 M.IsolateRef _isolate; | 37 M.IsolateRef _isolate; |
37 M.EventRepository _events; | 38 M.EventRepository _events; |
38 M.NotificationRepository _notifications; | 39 M.NotificationRepository _notifications; |
39 M.ClassRepository _classes; | 40 M.ClassRepository _classes; |
40 M.Class _object; | 41 M.Class _object; |
41 final _subclasses = <String, Iterable<M.Class>>{}; | 42 final _subclasses = <String, Iterable<M.Class>>{}; |
42 final _mixins = <String, List<M.Instance>>{}; | 43 final _mixins = <String, List<M.Instance>>{}; |
43 | 44 |
44 factory ClassTreeElement(M.VMRef vm, M.IsolateRef isolate, | 45 factory ClassTreeElement( |
45 M.EventRepository events, | 46 M.VMRef vm, |
46 M.NotificationRepository notifications, | 47 M.IsolateRef isolate, |
47 M.ClassRepository classes, | 48 M.EventRepository events, |
48 {RenderingQueue queue}) { | 49 M.NotificationRepository notifications, |
| 50 M.ClassRepository classes, |
| 51 {RenderingQueue queue}) { |
49 assert(vm != null); | 52 assert(vm != null); |
50 assert(isolate != null); | 53 assert(isolate != null); |
51 assert(events != null); | 54 assert(events != null); |
52 assert(notifications != null); | 55 assert(notifications != null); |
53 assert(classes != null); | 56 assert(classes != null); |
54 ClassTreeElement e = document.createElement(tag.name); | 57 ClassTreeElement e = document.createElement(tag.name); |
55 e._r = new RenderingScheduler(e, queue: queue); | 58 e._r = new RenderingScheduler(e, queue: queue); |
56 e._vm = vm; | 59 e._vm = vm; |
57 e._isolate = isolate; | 60 e._isolate = isolate; |
58 e._events = events; | 61 e._events = events; |
(...skipping 26 matching lines...) Expand all Loading... |
85 new NavTopMenuElement(queue: _r.queue), | 88 new NavTopMenuElement(queue: _r.queue), |
86 new NavVMMenuElement(_vm, _events, queue: _r.queue), | 89 new NavVMMenuElement(_vm, _events, queue: _r.queue), |
87 new NavIsolateMenuElement(_isolate, _events, queue: _r.queue), | 90 new NavIsolateMenuElement(_isolate, _events, queue: _r.queue), |
88 navMenu('class hierarchy'), | 91 navMenu('class hierarchy'), |
89 new NavNotifyElement(_notifications, queue: _r.queue) | 92 new NavNotifyElement(_notifications, queue: _r.queue) |
90 ]), | 93 ]), |
91 new DivElement() | 94 new DivElement() |
92 ..classes = ['content-centered'] | 95 ..classes = ['content-centered'] |
93 ..children = [ | 96 ..children = [ |
94 new HeadingElement.h1()..text = 'Class Hierarchy', | 97 new HeadingElement.h1()..text = 'Class Hierarchy', |
95 new BRElement(), new HRElement(), | 98 new BRElement(), |
96 _object == null ? (new HeadingElement.h2()..text = 'Loading...') | 99 new HRElement(), |
97 : _createTree() | 100 _object == null |
| 101 ? (new HeadingElement.h2()..text = 'Loading...') |
| 102 : _createTree() |
98 ] | 103 ] |
99 ]; | 104 ]; |
100 } | 105 } |
101 | 106 |
102 Element _createTree() { | 107 Element _createTree() { |
103 _tree = new VirtualTreeElement(_create, _update, _children, | 108 _tree = new VirtualTreeElement(_create, _update, _children, |
104 items: [_object], queue: _r.queue); | 109 items: [_object], queue: _r.queue); |
105 _tree.expand(_object, autoExpandSingleChildNodes: true); | 110 _tree.expand(_object, autoExpandSingleChildNodes: true); |
106 return _tree; | 111 return _tree; |
107 } | 112 } |
108 | 113 |
109 Future _refresh() async { | 114 Future _refresh() async { |
110 _object = null; | 115 _object = null; |
111 _subclasses.clear(); | 116 _subclasses.clear(); |
112 _mixins.clear(); | 117 _mixins.clear(); |
113 _object = await _register(await _classes.getObject(_isolate)); | 118 _object = await _register(await _classes.getObject(_isolate)); |
114 _r.dirty(); | 119 _r.dirty(); |
115 } | 120 } |
116 | 121 |
117 Future<M.Class> _register(M.Class cls) async { | 122 Future<M.Class> _register(M.Class cls) async { |
118 _subclasses[cls.id] = await Future.wait( | 123 _subclasses[cls.id] = await Future.wait( |
119 (await Future.wait(cls.subclasses.map(_getActualChildrens))) | 124 (await Future.wait(cls.subclasses.map(_getActualChildrens))) |
120 .expand((f) => f) | 125 .expand((f) => f) |
121 .map(_register) | 126 .map(_register)); |
122 ); | |
123 return cls; | 127 return cls; |
124 } | 128 } |
125 | 129 |
126 Future<Iterable<M.Class>> _getActualChildrens(M.ClassRef ref) async { | 130 Future<Iterable<M.Class>> _getActualChildrens(M.ClassRef ref) async { |
127 var cls = await _classes.get(_isolate, ref.id); | 131 var cls = await _classes.get(_isolate, ref.id); |
128 if (cls.isPatch) { | 132 if (cls.isPatch) { |
129 return const []; | 133 return const []; |
130 } | 134 } |
131 if (cls.mixin == null) { | 135 if (cls.mixin == null) { |
132 return [cls]; | 136 return [cls]; |
133 } | 137 } |
134 return (await Future.wait(cls.subclasses.map(_getActualChildrens))) | 138 return (await Future.wait(cls.subclasses.map(_getActualChildrens))) |
135 .expand((f) => f) | 139 .expand((f) => f) |
136 ..forEach((subcls) { | 140 ..forEach((subcls) { |
137 _mixins[subcls.id] = (_mixins[subcls.id] ?? [])..add(cls.mixin); | 141 _mixins[subcls.id] = (_mixins[subcls.id] ?? [])..add(cls.mixin); |
138 }); | 142 }); |
139 } | 143 } |
140 | 144 |
141 static Element _create(toggle) { | 145 static Element _create(toggle) { |
142 return new DivElement()..classes = ['class-tree-item'] | 146 return new DivElement() |
143 ..children = [ | 147 ..classes = ['class-tree-item'] |
144 new SpanElement()..classes = ['lines'], | 148 ..children = [ |
145 new ButtonElement()..classes = ['expander'] | 149 new SpanElement()..classes = ['lines'], |
146 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)), | 150 new ButtonElement() |
147 new SpanElement()..classes = ['name'] | 151 ..classes = ['expander'] |
148 ]; | 152 ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)), |
| 153 new SpanElement()..classes = ['name'] |
| 154 ]; |
149 } | 155 } |
150 | 156 |
151 void _update(HtmlElement el, M.Class cls, int index) { | 157 void _update(HtmlElement el, M.Class cls, int index) { |
152 virtualTreeUpdateLines(el.children[0], index); | 158 virtualTreeUpdateLines(el.children[0], index); |
153 if (cls.subclasses.isEmpty) { | 159 if (cls.subclasses.isEmpty) { |
154 el.children[1].text = ''; | 160 el.children[1].text = ''; |
155 } else { | 161 } else { |
156 el.children[1].text = _tree.isExpanded(cls) ? '▼' : '►'; | 162 el.children[1].text = _tree.isExpanded(cls) ? '▼' : '►'; |
157 } | 163 } |
158 el.children[2].children = [ | 164 el.children[2].children = [ |
159 new ClassRefElement(_isolate, cls, queue: _r.queue) | 165 new ClassRefElement(_isolate, cls, queue: _r.queue) |
160 ]; | 166 ]; |
161 if (_mixins[cls.id] != null) { | 167 if (_mixins[cls.id] != null) { |
162 el.children[2].children.addAll(_createMixins(_mixins[cls.id])); | 168 el.children[2].children.addAll(_createMixins(_mixins[cls.id])); |
163 } | 169 } |
164 } | 170 } |
165 | 171 |
166 List<Element> _createMixins(List<M.Instance> types) { | 172 List<Element> _createMixins(List<M.Instance> types) { |
167 final children = types.expand((type) => [ | 173 final children = types |
168 new SpanElement()..text = ', ', | 174 .expand((type) => [ |
169 type.typeClass == null | 175 new SpanElement()..text = ', ', |
170 ? (new SpanElement()..text = type.name.split('<').first) | 176 type.typeClass == null |
171 : new ClassRefElement(_isolate, type.typeClass, queue: _r.queue) | 177 ? (new SpanElement()..text = type.name.split('<').first) |
172 ]).toList(); | 178 : new ClassRefElement(_isolate, type.typeClass, |
| 179 queue: _r.queue) |
| 180 ]) |
| 181 .toList(); |
173 children.first.text = ' with '; | 182 children.first.text = ' with '; |
174 return children; | 183 return children; |
175 } | 184 } |
176 | 185 |
177 Iterable<M.Class> _children(M.Class cls) { | 186 Iterable<M.Class> _children(M.Class cls) { |
178 return _subclasses[cls.id]; | 187 return _subclasses[cls.id]; |
179 } | 188 } |
180 } | 189 } |
OLD | NEW |