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

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

Issue 19771010: implement dirty checking for @observable objects (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: logging for loops in dirty checking 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 part of observe; 5 part of observe;
6 6
7 /** The callback used in the [CompoundBinding.combinator] field. */ 7 /** The callback used in the [CompoundBinding.combinator] field. */
8 typedef Object CompoundBindingCombinator(Map objects); 8 typedef Object CompoundBindingCombinator(Map objects);
9 9
10 /** 10 /**
11 * Model-Driven Views contains a helper object which is useful for the 11 * CompoundBinding is an object which knows how to listen to multiple path
12 * implementation of a Custom Syntax. 12 * values (registered via [bind]) and invoke its [combinator] when one or more
13 * of the values have changed and set its [value] property to the return value
14 * of the function. When any value has changed, all current values are provided
15 * to the [combinator] in the single `values` argument.
16 *
17 * For example:
13 * 18 *
14 * var binding = new CompoundBinding((values) { 19 * var binding = new CompoundBinding((values) {
15 * var combinedValue; 20 * var combinedValue;
16 * // compute combinedValue based on the current values which are provided 21 * // compute combinedValue based on the current values which are provided
17 * return combinedValue; 22 * return combinedValue;
18 * }); 23 * });
19 * binding.bind('name1', obj1, path1); 24 * binding.bind('name1', obj1, path1);
20 * binding.bind('name2', obj2, path2); 25 * binding.bind('name2', obj2, path2);
21 * //... 26 * //...
22 * binding.bind('nameN', objN, pathN); 27 * binding.bind('nameN', objN, pathN);
23 *
24 * CompoundBinding is an object which knows how to listen to multiple path
25 * values (registered via [bind]) and invoke its [combinator] when one or more
26 * of the values have changed and set its [value] property to the return value
27 * of the function. When any value has changed, all current values are provided
28 * to the [combinator] in the single `values` argument.
29 */ 28 */
30 // TODO(jmesserly): rename to something that indicates it's a computed value? 29 // TODO(jmesserly): rename to something that indicates it's a computed value?
31 class CompoundBinding extends ObservableBase { 30 class CompoundBinding extends ChangeNotifierBase {
32 CompoundBindingCombinator _combinator; 31 CompoundBindingCombinator _combinator;
33 32
34 // TODO(jmesserly): ideally these would be String keys, but sometimes we 33 // TODO(jmesserly): ideally these would be String keys, but sometimes we
35 // use integers. 34 // use integers.
36 Map<dynamic, StreamSubscription> _bindings = new Map(); 35 Map<dynamic, StreamSubscription> _bindings = new Map();
37 Map _values = new Map(); 36 Map _values = new Map();
38 bool _scheduled = false; 37 bool _scheduled = false;
39 bool _disposed = false; 38 bool _disposed = false;
40 Object _value; 39 Object _value;
41 40
(...skipping 16 matching lines...) Expand all
58 57
59 get value => _value; 58 get value => _value;
60 59
61 void set value(newValue) { 60 void set value(newValue) {
62 _value = notifyPropertyChange(_VALUE, _value, newValue); 61 _value = notifyPropertyChange(_VALUE, _value, newValue);
63 } 62 }
64 63
65 void bind(name, model, String path) { 64 void bind(name, model, String path) {
66 unbind(name); 65 unbind(name);
67 66
67 // TODO(jmesserly): should we avoid observing until we are observed,
68 // similar to PathObserver? Similar for unobserving?
68 _bindings[name] = new PathObserver(model, path).bindSync((value) { 69 _bindings[name] = new PathObserver(model, path).bindSync((value) {
69 _values[name] = value; 70 _values[name] = value;
70 _scheduleResolve(); 71 _scheduleResolve();
71 }); 72 });
72 } 73 }
73 74
74 void unbind(name, {bool suppressResolve: false}) { 75 void unbind(name, {bool suppressResolve: false}) {
75 var binding = _bindings.remove(name); 76 var binding = _bindings.remove(name);
76 if (binding == null) return; 77 if (binding == null) return;
77 78
78 binding.cancel(); 79 binding.cancel();
79 _values.remove(name); 80 _values.remove(name);
80 if (!suppressResolve) _scheduleResolve(); 81 if (!suppressResolve) _scheduleResolve();
81 } 82 }
82 83
83 // TODO(rafaelw): Is this the right processing model? 84 // TODO(rafaelw): Is this the right processing model?
84 // TODO(rafaelw): Consider having a seperate ChangeSummary for 85 // TODO(rafaelw): Consider having a seperate ChangeSummary for
85 // CompoundBindings so to excess dirtyChecks. 86 // CompoundBindings so to excess dirtyChecks.
86 void _scheduleResolve() { 87 void _scheduleResolve() {
87 if (_scheduled) return; 88 if (_scheduled) return;
88 _scheduled = true; 89 _scheduled = true;
89 queueChangeRecords(resolve); 90 runAsync(resolve);
90 } 91 }
91 92
92 void resolve() { 93 void resolve() {
93 if (_disposed) return; 94 if (_disposed) return;
94 _scheduled = false; 95 _scheduled = false;
95 96
96 if (_combinator == null) { 97 if (_combinator == null) {
97 throw new StateError( 98 throw new StateError(
98 'CompoundBinding attempted to resolve without a combinator'); 99 'CompoundBinding attempted to resolve without a combinator');
99 } 100 }
100 101
101 value = _combinator(_values); 102 value = _combinator(_values);
102 } 103 }
103 104
104 void dispose() { 105 void dispose() {
105 for (var binding in _bindings.values) { 106 for (var binding in _bindings.values) {
106 binding.cancel(); 107 binding.cancel();
107 } 108 }
108 _bindings.clear(); 109 _bindings.clear();
109 _values.clear(); 110 _values.clear();
110 111
111 _disposed = true; 112 _disposed = true;
112 value = null; 113 value = null;
113 } 114 }
114 } 115 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698