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

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

Issue 17552019: Reorganize mdv and observe packages (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: tests passing Created 7 years, 5 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
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 // This library itself is undocumented and not supported for end use. 5 /**
6 // Because dart:html must use some of this functionality, it has to be available 6 * *Warning*: this library is experimental, and APIs are subject to change.
7 // via a dart:* library. The public APIs are reexported via package:mdv_observe. 7 *
8 // Generally we try to keep this library minimal, with utility types and 8 * This library is used to observe changes to [Observable] types. It also
9 // functions in the package. 9 * has helpers to implement [Observable] objects.
10 library dart.mdv_observe_impl; 10 *
11 * For example:
12 *
13 * class Monster extends Unit with ObservableMixin {
14 * int _health = 100;
15 * get health => _health;
16 * set health(value) {
17 * _health = notifyChange(const Symbol('health'), _health, value);
18 * }
19 *
20 * void damage(int amount) {
21 * print('$this takes $amount damage!');
22 * health -= amount;
23 * }
24 *
25 * toString() => 'Monster with $health hit points';
26 * }
27 *
28 * main() {
29 * var obj = new Monster();
30 * obj.changes.listen((records) {
31 * print('Changes to $obj were: $records');
32 * });
33 * // Schedules asynchronous delivery of these changes
34 * obj.damage(10);
35 * obj.damage(20);
36 * print('done!');
37 * }
38 */
39 library observe;
11 40
12 import 'dart:async'; 41 import 'dart:async';
13 import 'dart:collection'; 42 import 'dart:collection';
43 import 'dart:mirrors';
14 44
15 part 'path_observer.dart'; 45 part 'src/compound_binding.dart';
46 part 'src/observable_box.dart';
47 part 'src/observable_list.dart';
48 part 'src/observable_map.dart';
49 part 'src/path_observer.dart';
16 50
17 /** 51 /**
18 * Interface representing an observable object. This is used by data in 52 * Interface representing an observable object. This is used by data in
19 * model-view architectures to notify interested parties of [changes]. 53 * model-view architectures to notify interested parties of [changes].
20 * 54 *
21 * This object does not require any specific technique to implement 55 * This object does not require any specific technique to implement
22 * observability. 56 * observability.
23 * 57 *
24 * You can use [ObservableMixin] as a base class or mixin to implement this. 58 * You can use [ObservableMixin] as a base class or mixin to implement this.
25 */ 59 */
26 abstract class Observable { 60 abstract class Observable {
27 /** 61 /**
28 * The stream of change records to this object. 62 * The stream of change records to this object.
29 * 63 *
30 * Changes should be delivered in asynchronous batches by calling 64 * Changes should be delivered in asynchronous batches by calling
31 * [queueChangeRecords]. 65 * [queueChangeRecords].
32 * 66 *
33 * [deliverChangeRecords] can be called to force delivery. 67 * [deliverChangeRecords] can be called to force delivery.
34 */ 68 */
35 Stream<List<ChangeRecord>> get changes; 69 Stream<List<ChangeRecord>> get changes;
36
37 // TODO(jmesserly): remove these ASAP.
38 /**
39 * *Warning*: this method is temporary until dart2js supports mirrors.
40 * Gets the value of a field or index. This should return null if it was
41 * not found.
42 */
43 getValueWorkaround(key);
44
45 /**
46 * *Warning*: this method is temporary until dart2js supports mirrors.
47 * Sets the value of a field or index. This should have no effect if the field
48 * was not found.
49 */
50 void setValueWorkaround(key, Object value);
51 } 70 }
52 71
53 /** 72 /**
54 * Base class implementing [Observable]. 73 * Base class implementing [Observable].
55 * 74 *
56 * When a field, property, or indexable item is changed, a derived class should 75 * When a field, property, or indexable item is changed, a derived class should
57 * call [notifyPropertyChange]. See that method for an example. 76 * call [notifyPropertyChange]. See that method for an example.
58 */ 77 */
59 typedef ObservableBase = Object with ObservableMixin; 78 typedef ObservableBase = Object with ObservableMixin;
60 79
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 /** Queues an action to happen during the [deliverChangeRecords] timeslice. */ 238 /** Queues an action to happen during the [deliverChangeRecords] timeslice. */
220 void queueChangeRecords(void deliverChanges()) { 239 void queueChangeRecords(void deliverChanges()) {
221 if (_deliverCallbacks == null) { 240 if (_deliverCallbacks == null) {
222 _deliverCallbacks = new Queue<Function>(); 241 _deliverCallbacks = new Queue<Function>();
223 runAsync(deliverChangeRecords); 242 runAsync(deliverChangeRecords);
224 } 243 }
225 _deliverCallbacks.add(deliverChanges); 244 _deliverCallbacks.add(deliverChanges);
226 } 245 }
227 246
228 Queue _deliverCallbacks; 247 Queue _deliverCallbacks;
248
249
250 /**
251 * Converts the [Iterable] or [Map] to an [ObservableList] or [ObservableMap],
252 * respectively. This is a convenience function to make it easier to convert
253 * literals into the corresponding observable collection type.
justinfagnani 2013/06/25 23:03:31 It may be obvious, but do you want to mention that
Jennifer Messerly 2013/06/26 23:09:12 attempted to clarify comment
254 *
255 * If [value] is not one of those collection types, or is already [Observable],
256 * it will be returned unmodified.
257 *
258 * If [value] is a [Map], the resulting value will use the appropriate kind of
259 * backing map: either [HashMap], [LinkedHashMap], or [SplayTreeMap].
260 *
261 * By default this performs a deep conversion, but you can set [deep] to false
262 * for a shallow conversion. This does not handle circular data structures.
263 */
264 // TODO(jmesserly): ObservableSet?
265 toObservable(value, {bool deep: true}) =>
266 deep ? _toObservableDeep(value) : _toObservableShallow(value);
267
268 _toObservableShallow(value) {
269 if (value is Observable) return value;
270 if (value is Map) return new ObservableMap.from(value);
271 if (value is Iterable) return new ObservableList.from(value);
272 return value;
273 }
274
275 _toObservableDeep(value) {
276 if (value is Observable) return value;
277 if (value is Map) {
278 var result = new ObservableMap._createFromType(value);
279 value.forEach((k, v) {
280 result[_toObservableDeep(k)] = _toObservableDeep(v);
281 });
282 return result;
283 }
284 if (value is Iterable) {
285 return new ObservableList.from(value.map(_toObservableDeep));
286 }
287 return value;
288 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698