Chromium Code Reviews| Index: pkg/polymer_expressions/lib/src/globals.dart |
| diff --git a/pkg/polymer_expressions/lib/src/globals.dart b/pkg/polymer_expressions/lib/src/globals.dart |
| index 281536df329557d2b7ecedbaf35c01262021bdd1..56836f3f4f19757d648184d87d3fa6cf26becf9f 100644 |
| --- a/pkg/polymer_expressions/lib/src/globals.dart |
| +++ b/pkg/polymer_expressions/lib/src/globals.dart |
| @@ -10,64 +10,60 @@ |
| // Code from https://github.com/google/quiver-dart/commit/52edc4baf37e99ff6a8f99c648b29b135fc0b880 |
|
Jennifer Messerly
2013/11/13 23:51:45
this comment seems wrong now :)
|
| library polymer_expressions.src.globals; |
| -import 'dart:collection'; |
| -import 'package:observe/observe.dart' show reflectable; |
| +import 'package:logging/logging.dart'; |
| +import 'package:observe/observe.dart'; |
| /** |
| * Returns an [Iterable] of [IndexedValue]s where the nth value holds the nth |
| * element of [iterable] and its index. |
| */ |
| -Iterable<IndexedValue> enumerate(Iterable iterable) => |
| - new EnumerateIterable(iterable); |
| +Iterable<IndexedValue> enumerate(Iterable iterable) { |
| + var i = 0; |
| + var result = iterable.map((e) => new IndexedValue(i++, e)); |
|
Jennifer Messerly
2013/11/13 23:51:45
I don't think this works. It looks awfully like a
Jennifer Messerly
2013/11/13 23:53:42
original context:
https://github.com/google/quiver
|
| + if (iterable is! ObservableList) return result; |
| -@reflectable class IndexedValue<V> { |
| - final int index; |
| - final V value; |
| - |
| - IndexedValue(this.index, this.value); |
| + result = new ObservableList.from(result); |
| + (iterable as ObservableList).listChanges.listen( |
| + (changes) => _propagateChange(iterable, result, changes)); |
| + return result; |
| } |
| -/** |
| - * An [Iterable] of [IndexedValue]s where the nth value holds the nth |
| - * element of [iterable] and its index. See [enumerate]. |
| - */ |
| -// This was inspired by MappedIterable internal to Dart collections. |
| -class EnumerateIterable<V> extends IterableBase<IndexedValue<V>> { |
| - final Iterable<V> _iterable; |
| - |
| - EnumerateIterable(this._iterable); |
| - |
| - Iterator<IndexedValue<V>> get iterator => |
| - new EnumerateIterator<V>(_iterable.iterator); |
| +class IndexedValue<V> { |
|
Jennifer Messerly
2013/11/13 23:51:45
should mixin Observable or probably ChangeNotifier
|
| + @observable int index; |
|
Jennifer Messerly
2013/11/13 23:51:45
make this immutable? so people don't accidentally
|
| + @reflectable final V value; |
| - // Length related functions are independent of the mapping. |
| - int get length => _iterable.length; |
| - bool get isEmpty => _iterable.isEmpty; |
| - |
| - // Index based lookup can be done before transforming. |
| - IndexedValue<V> get first => new IndexedValue<V>(0, _iterable.first); |
| - IndexedValue<V> get last => new IndexedValue<V>(length - 1, _iterable.last); |
| - IndexedValue<V> get single => new IndexedValue<V>(0, _iterable.single); |
| - IndexedValue<V> elementAt(int index) => |
| - new IndexedValue<V>(index, _iterable.elementAt(index)); |
| + IndexedValue(this.index, this.value); |
| } |
| -/** The [Iterator] returned by [EnumerateIterable.iterator]. */ |
| -class EnumerateIterator<V> extends Iterator<IndexedValue<V>> { |
| - final Iterator<V> _iterator; |
| - int _index = 0; |
| - IndexedValue<V> _current; |
| +final _logger = new Logger('polymer_expressions'); |
| + |
| +void _propagateChange(ObservableList original, ObservableList target, |
| + List<ListChangeRecord> changes) { |
| + // TODO(sigmund): maybe we can expose ObservableList._hasListObservers so we |
|
Jennifer Messerly
2013/11/13 23:51:45
problem is, you'd need the pair of observed/unobse
|
| + // can skip this work when nobody is listening? |
| - EnumerateIterator(this._iterator); |
| + for (var change in changes) { |
| + var index = change.index; |
| + var added = change.addedCount; |
| + var removed = change.removed.length; |
| + if (index < 0 || index > target.length) { |
| + _logger.error('enumerate filter seems to be in an inconsistent state. ' |
| + 'Please report an error at dartbug.com/new with some information ' |
| + 'to help us reproduce the problem.'); |
| + return; |
| + } |
| + |
| + // Apply the same changes on our view of the original list: |
| + target.removeRange(index, index + removed); |
| + for (int i = added - 1; i >= 0; i--) { |
| + target.insert(index, new IndexedValue(index + i, original[index + i])); |
| + } |
| - IndexedValue<V> get current => _current; |
| + // Update indices of the later [IndexedValue]s, if necessary. |
| + if (added == removed) continue; |
| - bool moveNext() { |
| - if (_iterator.moveNext()) { |
| - _current = new IndexedValue(_index++, _iterator.current); |
| - return true; |
| + for (int i = index + added; i < target.length; i++) { |
| + target[i].index = i; |
| } |
| - _current = null; |
| - return false; |
| } |
| } |