| 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 |