| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 part of mdv_observe; | 5 part of observe; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Represents an observable list of model values. If any items are added, | 8 * Represents an observable list of model values. If any items are added, |
| 9 * removed, or replaced, then observers that are listening to [changes] | 9 * removed, or replaced, then observers that are listening to [changes] |
| 10 * will be notified. | 10 * will be notified. |
| 11 */ | 11 */ |
| 12 // TODO(jmesserly): remove implements List<E> once we can extend ListBase<E> | 12 // TODO(jmesserly): remove implements List<E> once we can extend ListBase<E> |
| 13 class ObservableList<E> extends _ListBaseWorkaround with ObservableMixin | 13 class ObservableList<E> extends _ListBaseWorkaround with ObservableMixin |
| 14 implements List<E> { | 14 implements List<E> { |
| 15 List<ListChangeRecord> _records; | 15 List<ListChangeRecord> _records; |
| 16 | 16 |
| 17 static const _LENGTH = const Symbol('length'); | |
| 18 | |
| 19 /** The inner [List<E>] with the actual storage. */ | 17 /** The inner [List<E>] with the actual storage. */ |
| 20 final List<E> _list; | 18 final List<E> _list; |
| 21 | 19 |
| 22 /** | 20 /** |
| 23 * Creates an observable list of the given [length]. | 21 * Creates an observable list of the given [length]. |
| 24 * | 22 * |
| 25 * If no [length] argument is supplied an extendable list of | 23 * If no [length] argument is supplied an extendable list of |
| 26 * length 0 is created. | 24 * length 0 is created. |
| 27 * | 25 * |
| 28 * If a [length] argument is supplied, a fixed size list of that | 26 * If a [length] argument is supplied, a fixed size list of that |
| 29 * length is created. | 27 * length is created. |
| 30 */ | 28 */ |
| 31 ObservableList([int length]) | 29 ObservableList([int length]) |
| 32 : _list = length != null ? new List<E>(length) : <E>[]; | 30 : _list = length != null ? new List<E>(length) : <E>[]; |
| 33 | 31 |
| 34 /** | 32 /** |
| 35 * Creates an observable list with the elements of [other]. The order in | 33 * Creates an observable list with the elements of [other]. The order in |
| 36 * the list will be the order provided by the iterator of [other]. | 34 * the list will be the order provided by the iterator of [other]. |
| 37 */ | 35 */ |
| 38 factory ObservableList.from(Iterable<E> other) => | 36 factory ObservableList.from(Iterable<E> other) => |
| 39 new ObservableList<E>()..addAll(other); | 37 new ObservableList<E>()..addAll(other); |
| 40 | 38 |
| 41 // TODO(jmesserly): remove once we have mirrors | |
| 42 getValueWorkaround(key) => key == _LENGTH ? length : null; | |
| 43 | |
| 44 setValueWorkaround(key, value) { | |
| 45 if (key == _LENGTH) length = value; | |
| 46 } | |
| 47 | |
| 48 int get length => _list.length; | 39 int get length => _list.length; |
| 49 | 40 |
| 50 set length(int value) { | 41 set length(int value) { |
| 51 int len = _list.length; | 42 int len = _list.length; |
| 52 if (len == value) return; | 43 if (len == value) return; |
| 53 | 44 |
| 54 // Produce notifications if needed | 45 // Produce notifications if needed |
| 55 if (hasObservers) { | 46 if (hasObservers) { |
| 56 if (value < len) { | 47 if (value < len) { |
| 57 // Remove items, then adjust length. Note the reverse order. | 48 // Remove items, then adjust length. Note the reverse order. |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 // list modifications. | 214 // list modifications. |
| 224 // One simple idea: we can simply update the index map as we do the operations | 215 // One simple idea: we can simply update the index map as we do the operations |
| 225 // to the list, then produce the records at the end. | 216 // to the list, then produce the records at the end. |
| 226 void _summarizeRecords() { | 217 void _summarizeRecords() { |
| 227 int oldLength = length; | 218 int oldLength = length; |
| 228 for (var r in _records) { | 219 for (var r in _records) { |
| 229 oldLength += r.removedCount - r.addedCount; | 220 oldLength += r.removedCount - r.addedCount; |
| 230 } | 221 } |
| 231 | 222 |
| 232 if (length != oldLength) { | 223 if (length != oldLength) { |
| 233 notifyPropertyChange(_LENGTH, oldLength, length); | 224 notifyPropertyChange(const Symbol('length'), oldLength, length); |
| 234 } | 225 } |
| 235 | 226 |
| 236 if (_records.length == 1) { | 227 if (_records.length == 1) { |
| 237 notifyChange(_records[0]); | 228 notifyChange(_records[0]); |
| 238 _records = null; | 229 _records = null; |
| 239 return; | 230 return; |
| 240 } | 231 } |
| 241 | 232 |
| 242 var items = []; | 233 var items = []; |
| 243 for (int i = 0; i < oldLength; i++) items.add(i); | 234 for (int i = 0; i < oldLength; i++) items.add(i); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 } | 271 } |
| 281 | 272 |
| 282 offset += removed - added; | 273 offset += removed - added; |
| 283 } | 274 } |
| 284 } | 275 } |
| 285 } | 276 } |
| 286 | 277 |
| 287 // TODO(jmesserly): bogus type to workaround spurious VM bug with generic base | 278 // TODO(jmesserly): bogus type to workaround spurious VM bug with generic base |
| 288 // class and mixins. | 279 // class and mixins. |
| 289 abstract class _ListBaseWorkaround extends ListBase<dynamic> {} | 280 abstract class _ListBaseWorkaround extends ListBase<dynamic> {} |
| OLD | NEW |