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

Side by Side Diff: pkg/observe/lib/src/observable.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/metadata.dart ('k') | pkg/observe/lib/src/observable_box.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; 5 library observe.src.observable;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 9
10 // Note: ObservableProperty is in this list only for the unusual use case of 10 // Note: ObservableProperty is in this list only for the unusual use case of
11 // dart2js without deploy tool. The deploy tool (see "transformer.dart") will 11 // dart2js without deploy tool. The deploy tool (see "transformer.dart") will
12 // add the @reflectable annotation, which makes it work with Polymer's 12 // add the @reflectable annotation, which makes it work with Polymer's
13 // @published. 13 // @published.
14 @MirrorsUsed(metaTargets: const [Reflectable, ObservableProperty], 14 @MirrorsUsed(metaTargets: const [Reflectable, ObservableProperty],
15 override: 'observe.src.observable') 15 override: 'observe.src.observable')
16 import 'dart:mirrors'; 16 import 'dart:mirrors';
17 17
18 import 'package:observe/observe.dart'; 18 import 'package:observe/observe.dart';
19 19
20 // Note: this is an internal library so we can import it from tests. 20 // Note: this is an internal library so we can import it from tests.
21 // TODO(jmesserly): ideally we could import this with a prefix, but it caused 21 // TODO(jmesserly): ideally we could import this with a prefix, but it caused
22 // strange problems on the VM when I tested out the dirty-checking example 22 // strange problems on the VM when I tested out the dirty-checking example
23 // above. 23 // above.
24 import 'dirty_check.dart'; 24 import 'dirty_check.dart';
25 25
26 /** 26 /// Represents an object with observable properties. This is used by data in
27 * Represents an object with observable properties. This is used by data in 27 /// model-view architectures to notify interested parties of [changes] to the
28 * model-view architectures to notify interested parties of [changes] to the 28 /// object's properties (fields or getter/setter pairs).
29 * object's properties (fields or getter/setter pairs). 29 ///
30 * 30 /// The interface does not require any specific technique to implement
31 * The interface does not require any specific technique to implement 31 /// observability. You can implement it in the following ways:
32 * observability. You can implement it in the following ways: 32 ///
33 * 33 /// - extend or mixin this class, and let the application call [dirtyCheck]
34 * - extend or mixin this class, and let the application call [dirtyCheck] 34 /// periodically to check for changes to your object.
35 * periodically to check for changes to your object. 35 /// - extend or mixin [ChangeNotifier], and implement change notifications
36 * - extend or mixin [ChangeNotifier], and implement change notifications 36 /// manually by calling [notifyPropertyChange] from your setters.
37 * manually by calling [notifyPropertyChange] from your setters. 37 /// - implement this interface and provide your own implementation.
38 * - implement this interface and provide your own implementation.
39 */
40 abstract class Observable { 38 abstract class Observable {
41 /** 39 /// Performs dirty checking of objects that inherit from [Observable].
42 * Performs dirty checking of objects that inherit from [Observable]. 40 /// This scans all observed objects using mirrors and determines if any fields
43 * This scans all observed objects using mirrors and determines if any fields 41 /// have changed. If they have, it delivers the changes for the object.
44 * have changed. If they have, it delivers the changes for the object.
45 */
46 static void dirtyCheck() => dirtyCheckObservables(); 42 static void dirtyCheck() => dirtyCheckObservables();
47 43
48 StreamController _changes; 44 StreamController _changes;
49 InstanceMirror _mirror; 45 InstanceMirror _mirror;
50 46
51 Map<Symbol, Object> _values; 47 Map<Symbol, Object> _values;
52 List<ChangeRecord> _records; 48 List<ChangeRecord> _records;
53 49
54 /** 50 /// The stream of change records to this object. Records will be delivered
55 * The stream of change records to this object. Records will be delivered 51 /// asynchronously.
56 * asynchronously. 52 ///
57 * 53 /// [deliverChanges] can be called to force synchronous delivery.
58 * [deliverChanges] can be called to force synchronous delivery.
59 */
60 Stream<List<ChangeRecord>> get changes { 54 Stream<List<ChangeRecord>> get changes {
61 if (_changes == null) { 55 if (_changes == null) {
62 _changes = new StreamController.broadcast(sync: true, 56 _changes = new StreamController.broadcast(sync: true,
63 onListen: _observed, onCancel: _unobserved); 57 onListen: _observed, onCancel: _unobserved);
64 } 58 }
65 return _changes.stream; 59 return _changes.stream;
66 } 60 }
67 61
68 /** 62 /// True if this object has any observers, and should call
69 * True if this object has any observers, and should call 63 /// [notifyChange] for changes.
70 * [notifyChange] for changes.
71 */
72 bool get hasObservers => _changes != null && _changes.hasListener; 64 bool get hasObservers => _changes != null && _changes.hasListener;
73 65
74 void _observed() { 66 void _observed() {
75 // Register this object for dirty checking purposes. 67 // Register this object for dirty checking purposes.
76 registerObservable(this); 68 registerObservable(this);
77 69
78 var mirror = reflect(this); 70 var mirror = reflect(this);
79 var values = new Map<Symbol, Object>(); 71 var values = new Map<Symbol, Object>();
80 72
81 // Note: we scan for @observable regardless of whether the base type 73 // Note: we scan for @observable regardless of whether the base type
(...skipping 15 matching lines...) Expand all
97 break; 89 break;
98 } 90 }
99 } 91 }
100 } 92 }
101 } 93 }
102 94
103 _mirror = mirror; 95 _mirror = mirror;
104 _values = values; 96 _values = values;
105 } 97 }
106 98
107 /** Release data associated with observation. */ 99 /// Release data associated with observation.
108 void _unobserved() { 100 void _unobserved() {
109 // Note: we don't need to explicitly unregister from the dirty check list. 101 // Note: we don't need to explicitly unregister from the dirty check list.
110 // This will happen automatically at the next call to dirtyCheck. 102 // This will happen automatically at the next call to dirtyCheck.
111 if (_values != null) { 103 if (_values != null) {
112 _mirror = null; 104 _mirror = null;
113 _values = null; 105 _values = null;
114 } 106 }
115 } 107 }
116 108
117 /** 109 /// Synchronously deliver pending [changes]. Returns true if any records were
118 * Synchronously deliver pending [changes]. Returns true if any records were 110 /// delivered, otherwise false.
119 * delivered, otherwise false.
120 */
121 // TODO(jmesserly): this is a bit different from the ES Harmony version, which 111 // TODO(jmesserly): this is a bit different from the ES Harmony version, which
122 // allows delivery of changes to a particular observer: 112 // allows delivery of changes to a particular observer:
123 // http://wiki.ecmascript.org/doku.php?id=harmony:observe#object.deliverchange records 113 // http://wiki.ecmascript.org/doku.php?id=harmony:observe#object.deliverchange records
124 // 114 //
125 // The rationale for that, and for async delivery in general, is the principal 115 // The rationale for that, and for async delivery in general, is the principal
126 // that you shouldn't run code (observers) when it doesn't expect to be run. 116 // that you shouldn't run code (observers) when it doesn't expect to be run.
127 // If you do that, you risk violating invariants that the code assumes. 117 // If you do that, you risk violating invariants that the code assumes.
128 // 118 //
129 // For this reason, we need to match the ES Harmony version. The way we can do 119 // For this reason, we need to match the ES Harmony version. The way we can do
130 // this in Dart is to add a method on StreamSubscription (possibly by 120 // this in Dart is to add a method on StreamSubscription (possibly by
(...skipping 21 matching lines...) Expand all
152 _values[name] = newValue; 142 _values[name] = newValue;
153 } 143 }
154 }); 144 });
155 145
156 if (records == null) return false; 146 if (records == null) return false;
157 147
158 _changes.add(new UnmodifiableListView<ChangeRecord>(records)); 148 _changes.add(new UnmodifiableListView<ChangeRecord>(records));
159 return true; 149 return true;
160 } 150 }
161 151
162 /** 152 /// Notify that the field [name] of this object has been changed.
163 * Notify that the field [name] of this object has been changed. 153 ///
164 * 154 /// The [oldValue] and [newValue] are also recorded. If the two values are
165 * The [oldValue] and [newValue] are also recorded. If the two values are 155 /// equal, no change will be recorded.
166 * equal, no change will be recorded. 156 ///
167 * 157 /// For convenience this returns [newValue].
168 * For convenience this returns [newValue].
169 */
170 notifyPropertyChange(Symbol field, Object oldValue, Object newValue) 158 notifyPropertyChange(Symbol field, Object oldValue, Object newValue)
171 => notifyPropertyChangeHelper(this, field, oldValue, newValue); 159 => notifyPropertyChangeHelper(this, field, oldValue, newValue);
172 160
173 /** 161 /// Notify observers of a change.
174 * Notify observers of a change. 162 ///
175 * 163 /// For most objects [Observable.notifyPropertyChange] is more convenient, but
176 * For most objects [Observable.notifyPropertyChange] is more convenient, but 164 /// collections sometimes deliver other types of changes such as a
177 * collections sometimes deliver other types of changes such as a 165 /// [ListChangeRecord].
178 * [ListChangeRecord]. 166 ///
179 * 167 /// Notes:
180 * Notes: 168 /// - This is *not* required for fields if you mixin or extend [Observable],
181 * - This is *not* required for fields if you mixin or extend [Observable], 169 /// but you can use it for computed properties.
182 * but you can use it for computed properties. 170 /// - Unlike [ChangeNotifier] this will not schedule [deliverChanges]; use
183 * - Unlike [ChangeNotifier] this will not schedule [deliverChanges]; use 171 /// [Observable.dirtyCheck] instead.
184 * [Observable.dirtyCheck] instead.
185 */
186 void notifyChange(ChangeRecord record) { 172 void notifyChange(ChangeRecord record) {
187 if (!hasObservers) return; 173 if (!hasObservers) return;
188 174
189 if (_records == null) _records = []; 175 if (_records == null) _records = [];
190 _records.add(record); 176 _records.add(record);
191 } 177 }
192 } 178 }
193 179
194 // TODO(jmesserly): remove the instance method and make this top-level method 180 // TODO(jmesserly): remove the instance method and make this top-level method
195 // public instead? 181 // public instead?
196 // NOTE: this is not exported publically. 182 // NOTE: this is not exported publically.
197 notifyPropertyChangeHelper(Observable obj, Symbol field, Object oldValue, 183 notifyPropertyChangeHelper(Observable obj, Symbol field, Object oldValue,
198 Object newValue) { 184 Object newValue) {
199 185
200 if (obj.hasObservers && oldValue != newValue) { 186 if (obj.hasObservers && oldValue != newValue) {
201 obj.notifyChange(new PropertyChangeRecord(obj, field, oldValue, newValue)); 187 obj.notifyChange(new PropertyChangeRecord(obj, field, oldValue, newValue));
202 } 188 }
203 return newValue; 189 return newValue;
204 } 190 }
205 191
206 // NOTE: this is not exported publically. 192 // NOTE: this is not exported publically.
207 final objectType = reflectClass(Object); 193 final objectType = reflectClass(Object);
OLDNEW
« no previous file with comments | « pkg/observe/lib/src/metadata.dart ('k') | pkg/observe/lib/src/observable_box.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698