OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'dart:html'; | 6 import 'dart:html'; |
7 import 'dart:math' as Math; | 7 import 'dart:math' as Math; |
8 import 'package:observatory/src/elements/containers/virtual_collection.dart'; | 8 import 'package:observatory/src/elements/containers/virtual_collection.dart'; |
9 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; | 9 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; |
10 import 'package:observatory/src/elements/helpers/tag.dart'; | 10 import 'package:observatory/src/elements/helpers/tag.dart'; |
11 | 11 |
12 typedef HtmlElement VirtualTreeCreateCallback( | 12 typedef HtmlElement VirtualTreeCreateCallback( |
13 toggle({bool autoToggleSingleChildNodes, bool autoToggleWholeTree})); | 13 toggle({bool autoToggleSingleChildNodes, bool autoToggleWholeTree})); |
14 typedef void VirtualTreeUpdateCallback(HtmlElement el, dynamic item, int depth); | 14 typedef void VirtualTreeUpdateCallback(HtmlElement el, dynamic item, int depth); |
15 typedef Iterable<dynamic> VritualTreeGetChildrenCallback(dynamic value); | 15 typedef Iterable<dynamic> VritualTreeGetChildrenCallback(dynamic value); |
16 | 16 |
17 void virtualTreeUpdateLines(SpanElement element, int n) { | 17 void virtualTreeUpdateLines(SpanElement element, int n) { |
18 n = Math.max(0, n); | 18 n = Math.max(0, n); |
19 while (element.children.length > n) { | 19 while (element.children.length > n) { |
20 element.children.removeLast(); | 20 element.children.removeLast(); |
21 } | 21 } |
22 while (element.children.length < n) { | 22 while (element.children.length < n) { |
23 element.children.add(new SpanElement()); | 23 element.children.add(new SpanElement()); |
24 } | 24 } |
25 } | 25 } |
26 | 26 |
27 class VirtualTreeElement extends HtmlElement implements Renderable { | 27 class VirtualTreeElement extends HtmlElement implements Renderable { |
28 static const tag = | 28 static const tag = const Tag<VirtualTreeElement>('virtual-tree', |
29 const Tag<VirtualTreeElement>('virtual-tree', dependencies: const [ | 29 dependencies: const [VirtualCollectionElement.tag]); |
30 VirtualCollectionElement.tag | |
31 ]); | |
32 | 30 |
33 RenderingScheduler<VirtualTreeElement> _r; | 31 RenderingScheduler<VirtualTreeElement> _r; |
34 | 32 |
35 Stream<RenderedEvent<VirtualTreeElement>> get onRendered => _r.onRendered; | 33 Stream<RenderedEvent<VirtualTreeElement>> get onRendered => _r.onRendered; |
36 | 34 |
37 VritualTreeGetChildrenCallback _children; | 35 VritualTreeGetChildrenCallback _children; |
38 List _items; | 36 List _items; |
39 List _depths; | 37 List _depths; |
40 final Set _expanded = new Set(); | 38 final Set _expanded = new Set(); |
41 | 39 |
(...skipping 10 matching lines...) Expand all Loading... |
52 {Iterable items: const [], RenderingQueue queue}) { | 50 {Iterable items: const [], RenderingQueue queue}) { |
53 assert(create != null); | 51 assert(create != null); |
54 assert(update != null); | 52 assert(update != null); |
55 assert(children != null); | 53 assert(children != null); |
56 assert(items != null); | 54 assert(items != null); |
57 VirtualTreeElement e = document.createElement(tag.name); | 55 VirtualTreeElement e = document.createElement(tag.name); |
58 e._r = new RenderingScheduler(e, queue: queue); | 56 e._r = new RenderingScheduler(e, queue: queue); |
59 e._children = children; | 57 e._children = children; |
60 e._collection = new VirtualCollectionElement(() { | 58 e._collection = new VirtualCollectionElement(() { |
61 var element; | 59 var element; |
62 return element = create(({bool autoToggleSingleChildNodes: false, | 60 return element = create(( |
| 61 {bool autoToggleSingleChildNodes: false, |
63 bool autoToggleWholeTree: false}) { | 62 bool autoToggleWholeTree: false}) { |
64 var item = e._collection.getItemFromElement(element); | 63 var item = e._collection.getItemFromElement(element); |
65 if (e.isExpanded(item)) { | 64 if (e.isExpanded(item)) { |
66 e.collapse(item, autoCollapseWholeTree: autoToggleWholeTree, | 65 e.collapse(item, |
| 66 autoCollapseWholeTree: autoToggleWholeTree, |
67 autoCollapseSingleChildNodes: autoToggleSingleChildNodes); | 67 autoCollapseSingleChildNodes: autoToggleSingleChildNodes); |
68 } else { | 68 } else { |
69 e.expand(item, autoExpandWholeTree: autoToggleWholeTree, | 69 e.expand(item, |
| 70 autoExpandWholeTree: autoToggleWholeTree, |
70 autoExpandSingleChildNodes: autoToggleSingleChildNodes); | 71 autoExpandSingleChildNodes: autoToggleSingleChildNodes); |
71 } | 72 } |
72 }); | 73 }); |
73 }, (HtmlElement el, dynamic item, int index) { | 74 }, (HtmlElement el, dynamic item, int index) { |
74 update(el, item, e._depths[index]); | 75 update(el, item, e._depths[index]); |
75 }, queue: queue); | 76 }, queue: queue); |
76 e._items = new List.unmodifiable(items); | 77 e._items = new List.unmodifiable(items); |
77 return e; | 78 return e; |
78 } | 79 } |
79 | 80 |
80 VirtualTreeElement.created() : super.created(); | 81 VirtualTreeElement.created() : super.created(); |
81 | 82 |
82 bool isExpanded(item) { | 83 bool isExpanded(item) { |
83 return _expanded.contains(item); | 84 return _expanded.contains(item); |
84 } | 85 } |
85 | 86 |
86 void expand(item, {bool autoExpandSingleChildNodes : false, | 87 void expand(item, |
| 88 {bool autoExpandSingleChildNodes: false, |
87 bool autoExpandWholeTree: false}) { | 89 bool autoExpandWholeTree: false}) { |
88 if (_expanded.add(item)) _r.dirty(); | 90 if (_expanded.add(item)) _r.dirty(); |
89 if (autoExpandWholeTree) { | 91 if (autoExpandWholeTree) { |
90 for (final child in _children(item)) { | 92 for (final child in _children(item)) { |
91 expand(child, autoExpandWholeTree: true); | 93 expand(child, autoExpandWholeTree: true); |
92 } | 94 } |
93 } else if (autoExpandSingleChildNodes) { | 95 } else if (autoExpandSingleChildNodes) { |
94 var children = _children(item); | 96 var children = _children(item); |
95 while (children.length == 1) { | 97 while (children.length == 1) { |
96 _expanded.add(children.first); | 98 _expanded.add(children.first); |
97 children = _children(children.first); | 99 children = _children(children.first); |
98 } | 100 } |
99 } | 101 } |
100 } | 102 } |
101 | 103 |
102 void collapse(item, {bool autoCollapseSingleChildNodes : false, | 104 void collapse(item, |
| 105 {bool autoCollapseSingleChildNodes: false, |
103 bool autoCollapseWholeTree: false}) { | 106 bool autoCollapseWholeTree: false}) { |
104 if (_expanded.remove(item)) _r.dirty(); | 107 if (_expanded.remove(item)) _r.dirty(); |
105 if (autoCollapseWholeTree) { | 108 if (autoCollapseWholeTree) { |
106 for (final child in _children(item)) { | 109 for (final child in _children(item)) { |
107 collapse(child, autoCollapseWholeTree: true); | 110 collapse(child, autoCollapseWholeTree: true); |
108 } | 111 } |
109 } else if (autoCollapseSingleChildNodes) { | 112 } else if (autoCollapseSingleChildNodes) { |
110 var children = _children(item); | 113 var children = _children(item); |
111 while (children.length == 1) { | 114 while (children.length == 1) { |
112 _expanded.remove(children.first); | 115 _expanded.remove(children.first); |
113 children = _children(children.first); | 116 children = _children(children.first); |
114 } | 117 } |
115 } | 118 } |
116 } | 119 } |
117 | 120 |
118 @override | 121 @override |
119 attached() { | 122 attached() { |
120 super.attached(); | 123 super.attached(); |
121 _r.enable(); | 124 _r.enable(); |
122 } | 125 } |
123 | 126 |
124 @override | 127 @override |
125 detached() { | 128 detached() { |
126 super.detached(); _r.disable(notify: true); | 129 super.detached(); |
| 130 _r.disable(notify: true); |
127 children = const []; | 131 children = const []; |
128 } | 132 } |
129 | 133 |
130 VirtualCollectionElement _collection; | 134 VirtualCollectionElement _collection; |
131 | 135 |
132 void render() { | 136 void render() { |
133 if (children.length == 0) { | 137 if (children.length == 0) { |
134 children = [_collection]; | 138 children = [_collection]; |
135 } | 139 } |
136 Iterable _toList(item) { | 140 Iterable _toList(item) { |
137 if (isExpanded(item)) { | 141 if (isExpanded(item)) { |
138 Iterable children = _children(item); | 142 Iterable children = _children(item); |
139 if (children.isNotEmpty) { | 143 if (children.isNotEmpty) { |
140 return [item]..addAll(children.expand(_toList)); | 144 return [item]..addAll(children.expand(_toList)); |
141 } | 145 } |
142 } | 146 } |
143 return [item]; | 147 return [item]; |
144 } | 148 } |
| 149 |
145 _collection.items = _items.expand(_toList); | 150 _collection.items = _items.expand(_toList); |
146 var depth = 0; | 151 var depth = 0; |
147 Iterable _toDepth(item) { | 152 Iterable _toDepth(item) { |
148 if (isExpanded(item)) { | 153 if (isExpanded(item)) { |
149 Iterable children = _children(item); | 154 Iterable children = _children(item); |
150 if (children.isNotEmpty) { | 155 if (children.isNotEmpty) { |
151 depth++; | 156 depth++; |
152 return children.expand(_toDepth).toList() | 157 return children.expand(_toDepth).toList()..insert(0, --depth); |
153 ..insert(0, --depth); | |
154 } | 158 } |
155 } | 159 } |
156 return [depth]; | 160 return [depth]; |
157 } | 161 } |
| 162 |
158 _depths = _items.expand(_toDepth).toList(); | 163 _depths = _items.expand(_toDepth).toList(); |
159 } | 164 } |
160 } | 165 } |
OLD | NEW |