Chromium Code Reviews| Index: runtime/observatory/lib/src/elements/containers/virtual_collection.dart |
| diff --git a/runtime/observatory/lib/src/elements/containers/virtual_collection.dart b/runtime/observatory/lib/src/elements/containers/virtual_collection.dart |
| index 049081de046459ab7645d5eaf4b26fa08eb985f6..5b5fcfcbe283c6ee85f239f880144fdb72047476 100644 |
| --- a/runtime/observatory/lib/src/elements/containers/virtual_collection.dart |
| +++ b/runtime/observatory/lib/src/elements/containers/virtual_collection.dart |
| @@ -21,6 +21,7 @@ class VirtualCollectionElement extends HtmlElement implements Renderable { |
| _r.onRendered; |
| VirtualCollectionCreateCallback _create; |
| + VirtualCollectionCreateCallback _createHeader; |
| VirtualCollectionUpdateCallback _update; |
| double _itemHeight; |
| int _top; |
| @@ -39,6 +40,7 @@ class VirtualCollectionElement extends HtmlElement implements Renderable { |
| factory VirtualCollectionElement(VirtualCollectionCreateCallback create, |
| VirtualCollectionUpdateCallback update, {Iterable items: const [], |
| + VirtualCollectionCreateCallback createHeader, |
| RenderingQueue queue}) { |
| assert(create != null); |
| assert(update != null); |
| @@ -46,6 +48,7 @@ class VirtualCollectionElement extends HtmlElement implements Renderable { |
| VirtualCollectionElement e = document.createElement(tag.name); |
| e._r = new RenderingScheduler(e, queue: queue); |
| e._create = create; |
| + e._createHeader = createHeader; |
| e._update = update; |
| e._items = new List.unmodifiable(items); |
| return e; |
| @@ -57,9 +60,8 @@ class VirtualCollectionElement extends HtmlElement implements Renderable { |
| attached() { |
| super.attached(); |
| _r.enable(); |
| - _top = 0; |
| - _height = getBoundingClientRect().height; |
| - _itemHeight = _computeItemHeight(); |
| + _top = null; |
| + _itemHeight = null; |
| _onScrollSubscription = onScroll.listen(_onScroll); |
| _onResizeSubscription = window.onResize.listen(_onResize); |
| } |
| @@ -73,6 +75,7 @@ class VirtualCollectionElement extends HtmlElement implements Renderable { |
| _onResizeSubscription.cancel(); |
| } |
| + final DivElement _header = new DivElement()..classes = const ['header']; |
| final DivElement _scroller = new DivElement()..classes = const ['scroller']; |
| final DivElement _shifter = new DivElement()..classes = const ['shifter']; |
| @@ -103,14 +106,30 @@ class VirtualCollectionElement extends HtmlElement implements Renderable { |
| static const double _inverse_preload = 1 / (_preload + 2); |
| void render() { |
| - _top = (scrollTop / _itemHeight).floor(); |
| + if (children.isEmpty) { |
| + children = [ |
| + _scroller |
| + ..children = [ |
| + _header, |
| + _shifter |
| + ..children = [_create()] |
| + ], |
| + ]; |
| + _itemHeight = _shifter.children[0].getBoundingClientRect().height; |
| + _height = getBoundingClientRect().height; |
| + } |
| + final top = (scrollTop / _itemHeight).floor(); |
| + |
| + _header.style.top = '${scrollTop}px'; |
| _scroller.style.height = '${_itemHeight*(_items.length)}px'; |
| final tail_length = (_height / _itemHeight / _preload).ceil(); |
| - _shifter.style.top = '${_itemHeight*(_top - tail_length)}px'; |
| final length = tail_length * 2 + tail_length * _preload; |
| if (_shifter.children.length < length) { |
| + if (_createHeader != null) { |
| + _header.children = [_createHeader()]; |
| + } |
| while (_shifter.children.length != length) { |
| var e = _create(); |
| e..style.display = 'hidden'; |
| @@ -118,36 +137,29 @@ class VirtualCollectionElement extends HtmlElement implements Renderable { |
| } |
| children = [ |
| _scroller |
| - ..children = [_shifter] |
| + ..children = [_header, _shifter], |
| ]; |
| - } |
| - int i = _top - tail_length; |
| - for (final HtmlElement e in _shifter.children) { |
| - if (0 <= i && i < _items.length) { |
| - e..style.display = null; |
| - _update(e, _items[i], i); |
| - } else { |
| - e.style.display = 'hidden'; |
| + _top = null; // force update; |
| + } |
| + if (_top == null || (top - _top).abs() >= tail_length) { |
|
Cutch
2016/08/17 14:28:44
Our style is to always wrap multiple if expression
cbernaschina
2016/08/17 17:01:27
Done.
|
| + _shifter.style.top = '${_itemHeight*(top-tail_length)}px'; |
| + int i = top - tail_length; |
| + for (final HtmlElement e in _shifter.children) { |
| + if (0 <= i && i < _items.length) { |
| + e..style.display = null; |
| + _update(e, _items[i], i); |
| + } else { |
| + e.style.display = 'hidden'; |
| + } |
| + i++; |
| } |
| - i++; |
| + _top = top; |
| } |
| } |
| - double _computeItemHeight() { |
| - final c = children; |
| - children = [_create()]; |
| - final height = children[0].getBoundingClientRect().height; |
| - children = c; |
| - return height; |
| - } |
| - |
| void _onScroll(_) { |
| - if(_r.isDirty) return; |
| - if ((scrollTop - _top * _itemHeight).abs() >= |
| - _shifter.children.length * _inverse_preload * _itemHeight) { |
| - _r.dirty(); |
| - } |
| + _r.dirty(); |
| } |
| void _onResize(_) { |