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

Side by Side Diff: pkg/observe/lib/src/observable_list.dart

Issue 178683003: [observe] use consistent comment style (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « pkg/observe/lib/src/observable_box.dart ('k') | pkg/observe/lib/src/observable_map.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 library observe.src.observable_list; 5 library observe.src.observable_list;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection' show ListBase, UnmodifiableListView; 8 import 'dart:collection' show ListBase, UnmodifiableListView;
9 import 'package:observe/observe.dart'; 9 import 'package:observe/observe.dart';
10 import 'list_diff.dart' show projectListSplices, calcSplices; 10 import 'list_diff.dart' show projectListSplices, calcSplices;
11 11
12 /** 12 /// Represents an observable list of model values. If any items are added,
13 * Represents an observable list of model values. If any items are added, 13 /// removed, or replaced, then observers that are listening to [changes]
14 * removed, or replaced, then observers that are listening to [changes] 14 /// will be notified.
15 * will be notified.
16 */
17 class ObservableList<E> extends ListBase<E> with ChangeNotifier { 15 class ObservableList<E> extends ListBase<E> with ChangeNotifier {
18 List<ListChangeRecord> _listRecords; 16 List<ListChangeRecord> _listRecords;
19 17
20 StreamController _listChanges; 18 StreamController _listChanges;
21 19
22 /** The inner [List<E>] with the actual storage. */ 20 /// The inner [List<E>] with the actual storage.
23 final List<E> _list; 21 final List<E> _list;
24 22
25 /** 23 /// Creates an observable list of the given [length].
26 * Creates an observable list of the given [length]. 24 ///
27 * 25 /// If no [length] argument is supplied an extendable list of
28 * If no [length] argument is supplied an extendable list of 26 /// length 0 is created.
29 * length 0 is created. 27 ///
30 * 28 /// If a [length] argument is supplied, a fixed size list of that
31 * If a [length] argument is supplied, a fixed size list of that 29 /// length is created.
32 * length is created.
33 */
34 ObservableList([int length]) 30 ObservableList([int length])
35 : _list = length != null ? new List<E>(length) : <E>[]; 31 : _list = length != null ? new List<E>(length) : <E>[];
36 32
37 /** 33 /// Creates an observable list with the elements of [other]. The order in
38 * Creates an observable list with the elements of [other]. The order in 34 /// the list will be the order provided by the iterator of [other].
39 * the list will be the order provided by the iterator of [other].
40 */
41 factory ObservableList.from(Iterable<E> other) => 35 factory ObservableList.from(Iterable<E> other) =>
42 new ObservableList<E>()..addAll(other); 36 new ObservableList<E>()..addAll(other);
43 37
44 /** 38 /// The stream of summarized list changes, delivered asynchronously.
45 * The stream of summarized list changes, delivered asynchronously. 39 ///
46 * 40 /// Each list change record contains information about an individual mutation.
47 * Each list change record contains information about an individual mutation. 41 /// The records are projected so they can be applied sequentially. For
48 * The records are projected so they can be applied sequentially. For example, 42 /// example, this set of mutations:
49 * this set of mutations: 43 ///
50 * 44 /// var model = new ObservableList.from(['a', 'b']);
51 * var model = new ObservableList.from(['a', 'b']); 45 /// model.listChanges.listen((records) => records.forEach(print));
52 * model.listChanges.listen((records) => records.forEach(print)); 46 /// model.removeAt(1);
53 * model.removeAt(1); 47 /// model.insertAll(0, ['c', 'd', 'e']);
54 * model.insertAll(0, ['c', 'd', 'e']); 48 /// model.removeRange(1, 3);
55 * model.removeRange(1, 3); 49 /// model.insert(1, 'f');
56 * model.insert(1, 'f'); 50 ///
57 * 51 /// The change records will be summarized so they can be "played back", using
58 * The change records will be summarized so they can be "played back", using 52 /// the final list positions to figure out which item was added:
59 * the final list positions to figure out which item was added: 53 ///
60 * 54 /// #<ListChangeRecord index: 0, removed: [], addedCount: 2>
61 * #<ListChangeRecord index: 0, removed: [], addedCount: 2> 55 /// #<ListChangeRecord index: 3, removed: [b], addedCount: 0>
62 * #<ListChangeRecord index: 3, removed: [b], addedCount: 0> 56 ///
63 * 57 /// [deliverChanges] can be called to force synchronous delivery.
64 * [deliverChanges] can be called to force synchronous delivery.
65 */
66 Stream<List<ListChangeRecord>> get listChanges { 58 Stream<List<ListChangeRecord>> get listChanges {
67 if (_listChanges == null) { 59 if (_listChanges == null) {
68 // TODO(jmesserly): split observed/unobserved notions? 60 // TODO(jmesserly): split observed/unobserved notions?
69 _listChanges = new StreamController.broadcast(sync: true, 61 _listChanges = new StreamController.broadcast(sync: true,
70 onCancel: () { _listChanges = null; }); 62 onCancel: () { _listChanges = null; });
71 } 63 }
72 return _listChanges.stream; 64 return _listChanges.stream;
73 } 65 }
74 66
75 bool get _hasListObservers => 67 bool get _hasListObservers =>
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 var records = projectListSplices(this, _listRecords); 257 var records = projectListSplices(this, _listRecords);
266 _listRecords = null; 258 _listRecords = null;
267 259
268 if (_hasListObservers && !records.isEmpty) { 260 if (_hasListObservers && !records.isEmpty) {
269 _listChanges.add(new UnmodifiableListView<ListChangeRecord>(records)); 261 _listChanges.add(new UnmodifiableListView<ListChangeRecord>(records));
270 return true; 262 return true;
271 } 263 }
272 return false; 264 return false;
273 } 265 }
274 266
275 /** 267 /// Calculates the changes to the list, if lacking individual splice mutation
276 * Calculates the changes to the list, if lacking individual splice mutation 268 /// information.
277 * information. 269 ///
278 * 270 /// This is not needed for change records produced by [ObservableList] itself,
279 * This is not needed for change records produced by [ObservableList] itself, 271 /// but it can be used if the list instance was replaced by another list.
280 * but it can be used if the list instance was replaced by another list. 272 ///
281 * 273 /// The minimal set of splices can be synthesized given the previous state and
282 * The minimal set of splices can be synthesized given the previous state and 274 /// final state of a list. The basic approach is to calculate the edit
283 * final state of a list. The basic approach is to calculate the edit distance 275 /// distance matrix and choose the shortest path through it.
284 * matrix and choose the shortest path through it. 276 ///
285 * 277 /// Complexity is `O(l * p)` where `l` is the length of the current list and
286 * Complexity is `O(l * p)` where `l` is the length of the current list and 278 /// `p` is the length of the old list.
287 * `p` is the length of the old list.
288 */
289 static List<ListChangeRecord> calculateChangeRecords( 279 static List<ListChangeRecord> calculateChangeRecords(
290 List<Object> oldValue, List<Object> newValue) => 280 List<Object> oldValue, List<Object> newValue) =>
291 calcSplices(newValue, 0, newValue.length, oldValue, 0, oldValue.length); 281 calcSplices(newValue, 0, newValue.length, oldValue, 0, oldValue.length);
292 282
293 /** 283 /// Updates the [previous] list using the change [records]. For added items,
294 * Updates the [previous] list using the change [records]. For added items, 284 /// the [current] list is used to find the current value.
295 * the [current] list is used to find the current value.
296 */
297 static void applyChangeRecords(List<Object> previous, List<Object> current, 285 static void applyChangeRecords(List<Object> previous, List<Object> current,
298 List<ListChangeRecord> changeRecords) { 286 List<ListChangeRecord> changeRecords) {
299 287
300 if (identical(previous, current)) { 288 if (identical(previous, current)) {
301 throw new ArgumentError("can't use same list for previous and current"); 289 throw new ArgumentError("can't use same list for previous and current");
302 } 290 }
303 291
304 for (var change in changeRecords) { 292 for (var change in changeRecords) {
305 int addEnd = change.index + change.addedCount; 293 int addEnd = change.index + change.addedCount;
306 int removeEnd = change.index + change.removed.length; 294 int removeEnd = change.index + change.removed.length;
307 295
308 var addedItems = current.getRange(change.index, addEnd); 296 var addedItems = current.getRange(change.index, addEnd);
309 previous.replaceRange(change.index, removeEnd, addedItems); 297 previous.replaceRange(change.index, removeEnd, addedItems);
310 } 298 }
311 } 299 }
312 } 300 }
OLDNEW
« no previous file with comments | « pkg/observe/lib/src/observable_box.dart ('k') | pkg/observe/lib/src/observable_map.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698