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 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; |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 } | 248 } |
249 _listRecords.add(record); | 249 _listRecords.add(record); |
250 } | 250 } |
251 | 251 |
252 void _notifyChangeLength(int oldValue, int newValue) { | 252 void _notifyChangeLength(int oldValue, int newValue) { |
253 notifyPropertyChange(#length, oldValue, newValue); | 253 notifyPropertyChange(#length, oldValue, newValue); |
254 notifyPropertyChange(#isEmpty, oldValue == 0, newValue == 0); | 254 notifyPropertyChange(#isEmpty, oldValue == 0, newValue == 0); |
255 notifyPropertyChange(#isNotEmpty, oldValue != 0, newValue != 0); | 255 notifyPropertyChange(#isNotEmpty, oldValue != 0, newValue != 0); |
256 } | 256 } |
257 | 257 |
| 258 void discardListChages() { |
| 259 // Leave _listRecords set so we don't schedule another delivery. |
| 260 if (_listRecords != null) _listRecords = []; |
| 261 } |
| 262 |
258 bool deliverListChanges() { | 263 bool deliverListChanges() { |
259 if (_listRecords == null) return false; | 264 if (_listRecords == null) return false; |
260 var records = projectListSplices(this, _listRecords); | 265 var records = projectListSplices(this, _listRecords); |
261 _listRecords = null; | 266 _listRecords = null; |
262 | 267 |
263 if (_hasListObservers) { | 268 if (_hasListObservers && !records.isEmpty) { |
264 _listChanges.add(new UnmodifiableListView<ListChangeRecord>(records)); | 269 _listChanges.add(new UnmodifiableListView<ListChangeRecord>(records)); |
265 return true; | 270 return true; |
266 } | 271 } |
267 return false; | 272 return false; |
268 } | 273 } |
269 | 274 |
270 /** | 275 /** |
271 * Calculates the changes to the list, if lacking individual splice mutation | 276 * Calculates the changes to the list, if lacking individual splice mutation |
272 * information. | 277 * information. |
273 * | 278 * |
274 * This is not needed for change records produced by [ObservableList] itself, | 279 * This is not needed for change records produced by [ObservableList] itself, |
275 * 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. |
276 * | 281 * |
277 * 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 |
278 * final state of a list. The basic approach is to calculate the edit distance | 283 * final state of a list. The basic approach is to calculate the edit distance |
279 * matrix and choose the shortest path through it. | 284 * matrix and choose the shortest path through it. |
280 * | 285 * |
281 * 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 |
282 * `p` is the length of the old list. | 287 * `p` is the length of the old list. |
283 */ | 288 */ |
284 static List<ListChangeRecord> calculateChangeRecords( | 289 static List<ListChangeRecord> calculateChangeRecords( |
285 List<Object> oldValue, List<Object> newValue) => | 290 List<Object> oldValue, List<Object> newValue) => |
286 calcSplices(newValue, 0, newValue.length, oldValue, 0, oldValue.length); | 291 calcSplices(newValue, 0, newValue.length, oldValue, 0, oldValue.length); |
| 292 |
| 293 /** |
| 294 * Updates the [previous] list using the change [records]. For added items, |
| 295 * the [current] list is used to find the current value. |
| 296 */ |
| 297 static void applyChangeRecords(List<Object> previous, List<Object> current, |
| 298 List<ListChangeRecord> changeRecords) { |
| 299 |
| 300 if (identical(previous, current)) { |
| 301 throw new ArgumentError("can't use same list for previous and current"); |
| 302 } |
| 303 |
| 304 for (var change in changeRecords) { |
| 305 int addEnd = change.index + change.addedCount; |
| 306 int removeEnd = change.index + change.removed.length; |
| 307 |
| 308 var addedItems = current.getRange(change.index, addEnd); |
| 309 previous.replaceRange(change.index, removeEnd, addedItems); |
| 310 } |
| 311 } |
287 } | 312 } |
OLD | NEW |