Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(471)

Side by Side Diff: sky/sdk/lib/widgets/block_viewport.dart

Issue 1227823012: Move VariableHeightScrollable to sdk/lib/widgets (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 import 'dart:collection';
6
5 import '../rendering/block.dart'; 7 import '../rendering/block.dart';
6 import '../rendering/box.dart'; 8 import '../rendering/box.dart';
7 import '../rendering/object.dart'; 9 import '../rendering/object.dart';
8 import 'widget.dart'; 10 import 'widget.dart';
9 11
10 // return null if index is greater than index of last entry 12 // return null if index is greater than index of last entry
11 typedef Widget IndexedBuilder(int index); 13 typedef Widget IndexedBuilder(int index);
12 14
15 typedef void LayoutChangedCallback(
16 int firstVisibleWidgetIndex,
17 int visibleWidgetCount,
18 UnmodifiableListView<double> widgetOffsets,
19 bool lastWidgetReached);
Hixie 2015/07/10 22:51:38 paren on its own line
hansmuller 2015/07/10 23:42:05 Done.
20
13 class _Key { 21 class _Key {
14 const _Key(this.type, this.key); 22 const _Key(this.type, this.key);
15 factory _Key.fromWidget(Widget widget) => new _Key(widget.runtimeType, widget. key); 23 factory _Key.fromWidget(Widget widget) => new _Key(widget.runtimeType, widget. key);
16 final Type type; 24 final Type type;
17 final String key; 25 final String key;
18 bool operator ==(other) => other is _Key && other.type == type && other.key == key; 26 bool operator ==(other) => other is _Key && other.type == type && other.key == key;
19 int get hashCode => 373 * 37 * type.hashCode + key.hashCode; 27 int get hashCode => 373 * 37 * type.hashCode + key.hashCode;
20 } 28 }
21 29
22 class BlockViewport extends RenderObjectWrapper { 30 class BlockViewport extends RenderObjectWrapper {
23 BlockViewport({ this.builder, this.startOffset, this.token, String key }) 31 BlockViewport({ this.builder, this.startOffset, this.token, this.onLayoutChang ed, String key })
24 : super(key: key); 32 : super(key: key);
25 33
26 IndexedBuilder builder; 34 IndexedBuilder builder;
27 double startOffset; 35 double startOffset;
28 Object token; 36 Object token;
37 LayoutChangedCallback onLayoutChanged;
29 38
30 RenderBlockViewport get root => super.root; 39 RenderBlockViewport get root => super.root;
31 RenderBlockViewport createNode() => new RenderBlockViewport(); 40 RenderBlockViewport createNode() => new RenderBlockViewport();
32 41
33 Map<_Key, Widget> _childrenByKey = new Map<_Key, Widget>(); 42 Map<_Key, Widget> _childrenByKey = new Map<_Key, Widget>();
34 43
35 void walkChildren(WidgetTreeWalker walker) { 44 void walkChildren(WidgetTreeWalker walker) {
36 for (Widget child in _childrenByKey.values) 45 for (Widget child in _childrenByKey.values)
37 walker(child); 46 walker(child);
38 } 47 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 super.didUnmount(); 85 super.didUnmount();
77 } 86 }
78 87
79 // _offsets contains the offsets of each child from the top of the 88 // _offsets contains the offsets of each child from the top of the
80 // list up to the last one we've ever created, and the offset of the 89 // list up to the last one we've ever created, and the offset of the
81 // end of the last one. If there's no children, then the only offset 90 // end of the last one. If there's no children, then the only offset
82 // is 0.0. 91 // is 0.0.
83 List<double> _offsets = <double>[0.0]; 92 List<double> _offsets = <double>[0.0];
84 int _currentStartIndex = 0; 93 int _currentStartIndex = 0;
85 int _currentChildCount = 0; 94 int _currentChildCount = 0;
95 bool _lastWidgetReached = false;
Hixie 2015/07/10 22:51:37 lastWidgetReached would store a Widget. If you wan
hansmuller 2015/07/10 23:42:05 I've changed all the fooWidget names I added to fo
86 96
87 int _findIndexForOffsetBeforeOrAt(double offset) { 97 int _findIndexForOffsetBeforeOrAt(double offset) {
88 int left = 0; 98 int left = 0;
89 int right = _offsets.length - 1; 99 int right = _offsets.length - 1;
90 while (right >= left) { 100 while (right >= left) {
91 int middle = left + ((right - left) ~/ 2); 101 int middle = left + ((right - left) ~/ 2);
92 if (_offsets[middle] < offset) { 102 if (_offsets[middle] < offset) {
93 left = middle + 1; 103 left = middle + 1;
94 } else if (_offsets[middle] > offset) { 104 } else if (_offsets[middle] > offset) {
95 right = middle - 1; 105 right = middle - 1;
(...skipping 10 matching lines...) Expand all
106 retainStatefulRenderObjectWrapper(newNode); 116 retainStatefulRenderObjectWrapper(newNode);
107 if (startOffset != newNode.startOffset) { 117 if (startOffset != newNode.startOffset) {
108 _dirty = true; 118 _dirty = true;
109 startOffset = newNode.startOffset; 119 startOffset = newNode.startOffset;
110 } 120 }
111 if (token != newNode.token || builder != newNode.builder) { 121 if (token != newNode.token || builder != newNode.builder) {
112 _dirty = true; 122 _dirty = true;
113 builder = newNode.builder; 123 builder = newNode.builder;
114 token = newNode.token; 124 token = newNode.token;
115 _offsets = <double>[0.0]; 125 _offsets = <double>[0.0];
126 _lastWidgetReached = false;
116 } 127 }
117 return true; 128 return true;
118 } 129 }
119 130
120 void syncRenderObject(BlockViewport old) { 131 void syncRenderObject(BlockViewport old) {
121 super.syncRenderObject(old); 132 super.syncRenderObject(old);
122 if (_dirty) { 133 if (_dirty) {
123 root.markNeedsLayout(); 134 root.markNeedsLayout();
124 } else { 135 } else {
125 if (_currentChildCount > 0) { 136 if (_currentChildCount > 0) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 startIndex = 0; 199 startIndex = 0;
189 if (_offsets.length > 1) { 200 if (_offsets.length > 1) {
190 haveChildren = true; 201 haveChildren = true;
191 } else { 202 } else {
192 Widget widget = _getWidget(startIndex, innerConstraints); 203 Widget widget = _getWidget(startIndex, innerConstraints);
193 if (widget != null) { 204 if (widget != null) {
194 newChildren[new _Key.fromWidget(widget)] = widget; 205 newChildren[new _Key.fromWidget(widget)] = widget;
195 builtChildren[startIndex] = widget; 206 builtChildren[startIndex] = widget;
196 haveChildren = true; 207 haveChildren = true;
197 } else { 208 } else {
198 haveChildren = false; 209 haveChildren = false;
Hixie 2015/07/10 22:51:37 i think this also means we've reached the end, no?
hansmuller 2015/07/10 23:42:05 Yes.
199 } 210 }
200 } 211 }
201 } else { 212 } else {
202 startIndex = _findIndexForOffsetBeforeOrAt(startOffset); 213 startIndex = _findIndexForOffsetBeforeOrAt(startOffset);
203 if (startIndex == _offsets.length - 1) { 214 if (startIndex == _offsets.length - 1) {
204 // We don't have an offset on the list that is beyond the start offset. 215 // We don't have an offset on the list that is beyond the start offset.
205 assert(_offsets.last <= startOffset); 216 assert(_offsets.last <= startOffset);
206 // Fill the list until this isn't true or until we know that the 217 // Fill the list until this isn't true or until we know that the
207 // list is complete (and thus we are overscrolled). 218 // list is complete (and thus we are overscrolled).
208 while (true) { 219 while (true) {
209 Widget widget = _getWidget(startIndex, innerConstraints); 220 Widget widget = _getWidget(startIndex, innerConstraints);
210 if (widget == null) 221 if (widget == null)
211 break; 222 break;
Hixie 2015/07/10 22:51:37 i think you have to also flag the end here?
hansmuller 2015/07/10 23:42:05 Oops, yes.
212 _Key widgetKey = new _Key.fromWidget(widget); 223 _Key widgetKey = new _Key.fromWidget(widget);
213 if (_offsets.last > startOffset) { 224 if (_offsets.last > startOffset) {
214 newChildren[widgetKey] = widget; 225 newChildren[widgetKey] = widget;
215 builtChildren[startIndex] = widget; 226 builtChildren[startIndex] = widget;
216 break; 227 break;
217 } 228 }
218 if (!_childrenByKey.containsKey(widgetKey)) { 229 if (!_childrenByKey.containsKey(widgetKey)) {
219 // we don't actually need this one, release it 230 // we don't actually need this one, release it
220 syncChild(null, widget, null); 231 syncChild(null, widget, null);
221 } // else we'll get rid of it later, when we remove old children 232 } // else we'll get rid of it later, when we remove old children
222 startIndex += 1; 233 startIndex += 1;
223 assert(startIndex == _offsets.length - 1); 234 assert(startIndex == _offsets.length - 1);
224 } 235 }
225 if (_offsets.last > startOffset) { 236 if (_offsets.last > startOffset) {
226 // If we're here, we have at least one child, so our list has 237 // If we're here, we have at least one child, so our list has
227 // at least two offsets, the top of the child and the bottom 238 // at least two offsets, the top of the child and the bottom
228 // of the child. 239 // of the child.
229 assert(_offsets.length >= 2); 240 assert(_offsets.length >= 2);
230 assert(startIndex == _offsets.length - 2); 241 assert(startIndex == _offsets.length - 2);
231 haveChildren = true; 242 haveChildren = true;
232 } else { 243 } else {
233 // If we're here, there are no children to show. 244 // If we're here, there are no children to show.
234 haveChildren = false; 245 haveChildren = false;
235 } 246 }
236 } else { 247 } else {
237 haveChildren = true; 248 haveChildren = true;
238 } 249 }
239 } 250 }
240 assert(haveChildren != null); 251 assert(haveChildren != null);
Hixie 2015/07/10 22:51:37 assert that if haveChildren is false, that we've a
hansmuller 2015/07/10 23:42:06 Done.
241 252
242 assert(startIndex >= 0); 253 assert(startIndex >= 0);
243 assert(startIndex < _offsets.length); 254 assert(startIndex < _offsets.length);
244 255
245 int index = startIndex; 256 int index = startIndex;
246 if (haveChildren) { 257 if (haveChildren) {
247 // Build all the widgets we need. 258 // Build all the widgets we need.
248 root.startOffset = _offsets[index] - startOffset; 259 root.startOffset = _offsets[index] - startOffset;
249 while (_offsets[index] < endOffset) { 260 while (_offsets[index] < endOffset) {
250 if (!builtChildren.containsKey(index)) { 261 if (!builtChildren.containsKey(index)) {
251 Widget widget = _getWidget(index, innerConstraints); 262 Widget widget = _getWidget(index, innerConstraints);
252 if (widget == null) 263 if (widget == null) {
253 break; // reached the end of the list 264 _lastWidgetReached = true;
265 break;
266 }
254 newChildren[new _Key.fromWidget(widget)] = widget; 267 newChildren[new _Key.fromWidget(widget)] = widget;
255 builtChildren[index] = widget; 268 builtChildren[index] = widget;
256 } 269 }
257 assert(builtChildren[index] != null); 270 assert(builtChildren[index] != null);
258 index += 1; 271 index += 1;
259 } 272 }
260 } 273 }
261 274
262 // Remove any old children. 275 // Remove any old children.
263 for (_Key oldChildKey in _childrenByKey.keys) { 276 for (_Key oldChildKey in _childrenByKey.keys) {
(...skipping 16 matching lines...) Expand all
280 root.add(widget.root, before: nextSibling); 293 root.add(widget.root, before: nextSibling);
281 } 294 }
282 widget.updateSlot(nextSibling); 295 widget.updateSlot(nextSibling);
283 nextSibling = widget.root; 296 nextSibling = widget.root;
284 } 297 }
285 } 298 }
286 299
287 _childrenByKey = newChildren; 300 _childrenByKey = newChildren;
288 _currentStartIndex = startIndex; 301 _currentStartIndex = startIndex;
289 _currentChildCount = _childrenByKey.length; 302 _currentChildCount = _childrenByKey.length;
303
304 if (onLayoutChanged != null) {
305 onLayoutChanged(
306 _currentStartIndex,
Hixie 2015/07/10 22:51:38 this should be indented with two spaces.
hansmuller 2015/07/10 23:42:05 Done.
307 _currentChildCount,
308 new UnmodifiableListView<double>(_offsets),
309 _lastWidgetReached);
Hixie 2015/07/10 22:51:37 closing paren should be on its own line.
hansmuller 2015/07/10 23:42:05 Done.
310 }
290 } 311 }
291 312
292 } 313 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698