| 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 /** | 5 /** |
| 6 * Helpers for observable objects. | 6 * Helpers for observable objects. |
| 7 * Intended for use with `package:mdv_observe`. | 7 * Intended for use with `package:mdv_observe`. |
| 8 */ | 8 */ |
| 9 library polymer.observe; | 9 library polymer.observe; |
| 10 | 10 |
| 11 import 'dart:async'; | 11 import 'dart:async'; |
| 12 // TODO(jmesserly): PathObserver should be in mdv_observe. | 12 // TODO(jmesserly): PathObserver should be in mdv_observe. |
| 13 import 'dart:html' show PathObserver; | 13 import 'dart:html' show PathObserver; |
| 14 import 'package:observe/observe.dart'; | 14 import 'package:observe/observe.dart'; |
| 15 | 15 |
| 16 /** | |
| 17 * Use `@observable` to make a property observable. | |
| 18 * The overhead will be minimal unless they are actually being observed. | |
| 19 */ | |
| 20 const observable = const _ObservableAnnotation(); | |
| 21 | |
| 22 /** | |
| 23 * The type of the `@observable` annotation. | |
| 24 * | |
| 25 * Library private because you should be able to use the [observable] field | |
| 26 * to get the one and only instance. We could make it public though, if anyone | |
| 27 * needs it for some reason. | |
| 28 */ | |
| 29 class _ObservableAnnotation { | |
| 30 const _ObservableAnnotation(); | |
| 31 } | |
| 32 | |
| 33 // Inspired by ArrayReduction at: | 16 // Inspired by ArrayReduction at: |
| 34 // https://raw.github.com/rafaelw/ChangeSummary/master/util/array_reduction.js | 17 // https://raw.github.com/rafaelw/ChangeSummary/master/util/array_reduction.js |
| 35 // The main difference is we support anything on the rich Dart Iterable API. | 18 // The main difference is we support anything on the rich Dart Iterable API. |
| 36 | 19 |
| 37 const _VALUE = const Symbol('value'); | 20 const _VALUE = const Symbol('value'); |
| 38 | 21 |
| 39 /** | 22 /** |
| 40 * Forwards an observable property from one object to another. For example: | 23 * Forwards an observable property from one object to another. For example: |
| 41 * | 24 * |
| 42 * class MyModel extends ObservableBase { | 25 * class MyModel extends ObservableBase { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 64 } | 47 } |
| 65 } | 48 } |
| 66 }); | 49 }); |
| 67 } | 50 } |
| 68 | 51 |
| 69 /** | 52 /** |
| 70 * Notify the property change. Shorthand for: | 53 * Notify the property change. Shorthand for: |
| 71 * | 54 * |
| 72 * target.notifyChange(new PropertyChangeRecord(targetName)); | 55 * target.notifyChange(new PropertyChangeRecord(targetName)); |
| 73 */ | 56 */ |
| 74 void notifyProperty(ObservableMixin target, Symbol targetName) { | 57 void notifyProperty(Observable target, Symbol targetName) { |
| 75 target.notifyChange(new PropertyChangeRecord(targetName)); | 58 target.notifyChange(new PropertyChangeRecord(targetName)); |
| 76 } | 59 } |
| 77 | 60 |
| 78 | 61 |
| 79 /** | 62 /** |
| 80 * Observes a path starting from each item in the list. | 63 * Observes a path starting from each item in the list. |
| 81 */ | 64 */ |
| 82 class ListPathObserver<E, P> extends ObservableBase { | 65 class ListPathObserver<E, P> extends ChangeNotifierBase { |
| 83 final ObservableList<E> list; | 66 final ObservableList<E> list; |
| 84 final String _itemPath; | 67 final String _itemPath; |
| 85 final List<PathObserver> _observers = <PathObserver>[]; | 68 final List<PathObserver> _observers = <PathObserver>[]; |
| 86 final List<StreamSubscription> _subs = <StreamSubscription>[]; | 69 final List<StreamSubscription> _subs = <StreamSubscription>[]; |
| 87 StreamSubscription _sub; | 70 StreamSubscription _sub; |
| 88 bool _scheduled = false; | 71 bool _scheduled = false; |
| 89 Iterable<P> _value; | 72 Iterable<P> _value; |
| 90 | 73 |
| 91 ListPathObserver(this.list, String path) | 74 ListPathObserver(this.list, String path) |
| 92 : _itemPath = path { | 75 : _itemPath = path { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 114 | 97 |
| 115 void _reduce() { | 98 void _reduce() { |
| 116 _scheduled = false; | 99 _scheduled = false; |
| 117 _value = _observers.map((o) => o.value); | 100 _value = _observers.map((o) => o.value); |
| 118 notifyChange(new PropertyChangeRecord(_VALUE)); | 101 notifyChange(new PropertyChangeRecord(_VALUE)); |
| 119 } | 102 } |
| 120 | 103 |
| 121 void _scheduleReduce(_) { | 104 void _scheduleReduce(_) { |
| 122 if (_scheduled) return; | 105 if (_scheduled) return; |
| 123 _scheduled = true; | 106 _scheduled = true; |
| 124 queueChangeRecords(_reduce); | 107 runAsync(_reduce); |
| 125 } | 108 } |
| 126 | 109 |
| 127 _observeItems(int lengthAdjust) { | 110 _observeItems(int lengthAdjust) { |
| 128 if (lengthAdjust > 0) { | 111 if (lengthAdjust > 0) { |
| 129 for (int i = 0; i < lengthAdjust; i++) { | 112 for (int i = 0; i < lengthAdjust; i++) { |
| 130 int len = _observers.length; | 113 int len = _observers.length; |
| 131 var pathObs = new PathObserver(list, '$len.$_itemPath'); | 114 var pathObs = new PathObserver(list, '$len.$_itemPath'); |
| 132 _subs.add(pathObs.values.listen(_scheduleReduce)); | 115 _subs.add(pathObs.changes.listen(_scheduleReduce)); |
| 133 _observers.add(pathObs); | 116 _observers.add(pathObs); |
| 134 } | 117 } |
| 135 } else if (lengthAdjust < 0) { | 118 } else if (lengthAdjust < 0) { |
| 136 for (int i = 0; i < -lengthAdjust; i++) { | 119 for (int i = 0; i < -lengthAdjust; i++) { |
| 137 _subs.removeLast().cancel(); | 120 _subs.removeLast().cancel(); |
| 138 } | 121 } |
| 139 int len = _observers.length; | 122 int len = _observers.length; |
| 140 _observers.removeRange(len + lengthAdjust, len); | 123 _observers.removeRange(len + lengthAdjust, len); |
| 141 } | 124 } |
| 142 } | 125 } |
| 143 | |
| 144 setValueWorkaround(key, value) {} | |
| 145 getValueWorkaround(key) => key == _VALUE ? value : null; | |
| 146 } | 126 } |
| OLD | NEW |