Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 import 'dart:async'; | |
| 6 import 'dart:html'; | |
| 7 import 'package:observatory/src/elements/containers/virtual_collection.dart'; | |
| 8 import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; | |
| 9 import 'package:observatory/src/elements/helpers/tag.dart'; | |
| 10 | |
| 11 typedef HtmlElement VirtualTreeCreateCallback( | |
| 12 toggle({bool toggleSingleChildNodes, bool toggleWholeTree})); | |
|
Cutch
2016/08/01 23:45:11
prefix both of these with "auto"
cbernaschina
2016/08/01 23:50:41
Done.
| |
| 13 typedef void VirtualTreeUpdateCallback(HtmlElement el, dynamic item, int depth); | |
| 14 typedef Iterable<dynamic> VritualTreeGetChildrenCallback(dynamic value); | |
| 15 | |
| 16 class VirtualTreeElement extends HtmlElement implements Renderable { | |
| 17 static const tag = | |
| 18 const Tag<VirtualTreeElement>('virtual-tree', dependencies: const [ | |
| 19 VirtualCollectionElement.tag | |
| 20 ]); | |
| 21 | |
| 22 RenderingScheduler<VirtualTreeElement> _r; | |
| 23 | |
| 24 Stream<RenderedEvent<VirtualTreeElement>> get onRendered => _r.onRendered; | |
| 25 | |
| 26 VritualTreeGetChildrenCallback _children; | |
| 27 List _items; | |
| 28 List _depths; | |
| 29 final Set _expanded = new Set(); | |
| 30 | |
| 31 List get items => _items; | |
| 32 | |
| 33 set items(Iterable value) { | |
| 34 _items = new List.unmodifiable(value); | |
| 35 _expanded.clear(); | |
| 36 _r.dirty(); | |
| 37 } | |
| 38 | |
| 39 factory VirtualTreeElement(VirtualTreeCreateCallback create, | |
| 40 VirtualTreeUpdateCallback update, VritualTreeGetChildrenCallback children, | |
| 41 {Iterable items: const [], RenderingQueue queue}) { | |
| 42 assert(create != null); | |
| 43 assert(update != null); | |
| 44 assert(children != null); | |
| 45 assert(items != null); | |
| 46 VirtualTreeElement e = document.createElement(tag.name); | |
| 47 e._r = new RenderingScheduler(e, queue: queue); | |
| 48 e._children = children; | |
| 49 e._collection = new VirtualCollectionElement(() { | |
| 50 var element; | |
| 51 return element = create(({bool toggleSingleChildNodes: false, | |
| 52 bool toggleWholeTree: false}) { | |
| 53 var item = e._collection.getItemFromElement(element); | |
| 54 if (e.isExpanded(item)) { | |
| 55 e.collapse(item, collapseSingleChildNodes: toggleSingleChildNodes, | |
| 56 collapseWholeTree: toggleWholeTree); | |
| 57 } else { | |
| 58 e.expand(item, expandSingleChildNodes: toggleSingleChildNodes, | |
| 59 expandWholeTree: toggleWholeTree); | |
| 60 } | |
| 61 }); | |
| 62 }, (HtmlElement el, dynamic item, int index) { | |
| 63 update(el, item, e._depths[index]); | |
| 64 }, queue: queue); | |
| 65 e._items = new List.unmodifiable(items); | |
| 66 return e; | |
| 67 } | |
| 68 | |
| 69 VirtualTreeElement.created() : super.created(); | |
| 70 | |
| 71 bool isExpanded(item) { | |
| 72 return _expanded.contains(item); | |
| 73 } | |
| 74 | |
| 75 void expand(item, {bool expandSingleChildNodes : false, | |
| 76 bool expandWholeTree: false}) { | |
| 77 if (_expanded.add(item)) _r.dirty(); | |
| 78 if (expandWholeTree) { | |
| 79 for (final child in _children(item)) { | |
| 80 expand(child, expandWholeTree: true); | |
| 81 } | |
| 82 } else if (expandSingleChildNodes) { | |
| 83 var children = _children(item); | |
| 84 while (children.length == 1) { | |
| 85 _expanded.add(children.first); | |
| 86 children = _children(children.first); | |
| 87 } | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 void collapse(item, {bool collapseSingleChildNodes : false, | |
| 92 bool collapseWholeTree: false}) { | |
| 93 if (_expanded.remove(item)) _r.dirty(); | |
| 94 if (collapseWholeTree) { | |
| 95 for (final child in _children(item)) { | |
| 96 collapse(child, collapseWholeTree: true); | |
| 97 } | |
| 98 } else if (collapseSingleChildNodes) { | |
| 99 var children = _children(item); | |
| 100 while (children.length == 1) { | |
| 101 _expanded.remove(children.first); | |
| 102 children = _children(children.first); | |
| 103 } | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 @override | |
| 108 attached() { | |
| 109 super.attached(); | |
| 110 _r.enable(); | |
| 111 } | |
| 112 | |
| 113 @override | |
| 114 detached() { | |
| 115 super.detached(); _r.disable(notify: true); | |
| 116 children = const []; | |
| 117 } | |
| 118 | |
| 119 VirtualCollectionElement _collection; | |
| 120 | |
| 121 void render() { | |
| 122 if (children.length == 0) { | |
| 123 children = [_collection]; | |
| 124 } | |
| 125 Iterable _toList(item) { | |
| 126 if (isExpanded(item)) { | |
| 127 Iterable children = _children(item); | |
| 128 if (children.isNotEmpty) { | |
| 129 return [item]..addAll(children.expand(_toList)); | |
| 130 } | |
| 131 } | |
| 132 return [item]; | |
| 133 } | |
| 134 _collection.items = _items.expand(_toList); | |
| 135 var depth = 0; | |
| 136 Iterable _toDepth(item) { | |
| 137 if (isExpanded(item)) { | |
| 138 Iterable children = _children(item); | |
| 139 if (children.isNotEmpty) { | |
| 140 depth++; | |
| 141 return children.expand(_toDepth).toList() | |
| 142 ..insert(0, --depth); | |
| 143 } | |
| 144 } | |
| 145 return [depth]; | |
| 146 } | |
| 147 _depths = _items.expand(_toDepth).toList(); | |
| 148 } | |
| 149 } | |
| OLD | NEW |