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 part of observe; | 5 part of observe; |
6 | 6 |
7 // TODO(jmesserly): this needs to be faster. We currently require multiple | 7 // TODO(jmesserly): this needs to be faster. We currently require multiple |
8 // lookups per key to get the old value. | 8 // lookups per key to get the old value. |
9 // TODO(jmesserly): this doesn't implement the precise interfaces like | 9 // TODO(jmesserly): this doesn't implement the precise interfaces like |
10 // LinkedHashMap, SplayTreeMap or HashMap. However it can use them for the | 10 // LinkedHashMap, SplayTreeMap or HashMap. However it can use them for the |
(...skipping 26 matching lines...) Expand all Loading... |
37 return '#<MapChangeRecord $kind $key>'; | 37 return '#<MapChangeRecord $kind $key>'; |
38 } | 38 } |
39 } | 39 } |
40 | 40 |
41 /** | 41 /** |
42 * Represents an observable map of model values. If any items are added, | 42 * Represents an observable map of model values. If any items are added, |
43 * removed, or replaced, then observers that are listening to [changes] | 43 * removed, or replaced, then observers that are listening to [changes] |
44 * will be notified. | 44 * will be notified. |
45 */ | 45 */ |
46 class ObservableMap<K, V> extends ChangeNotifierBase implements Map<K, V> { | 46 class ObservableMap<K, V> extends ChangeNotifierBase implements Map<K, V> { |
47 static const _LENGTH = const Symbol('length'); | |
48 | |
49 final Map<K, V> _map; | 47 final Map<K, V> _map; |
50 | 48 |
51 /** Creates an observable map. */ | 49 /** Creates an observable map. */ |
52 ObservableMap() : _map = new HashMap<K, V>(); | 50 ObservableMap() : _map = new HashMap<K, V>(); |
53 | 51 |
54 /** Creates a new observable map using a [LinkedHashMap]. */ | 52 /** Creates a new observable map using a [LinkedHashMap]. */ |
55 ObservableMap.linked() : _map = new LinkedHashMap<K, V>(); | 53 ObservableMap.linked() : _map = new LinkedHashMap<K, V>(); |
56 | 54 |
57 /** Creates a new observable map using a [SplayTreeMap]. */ | 55 /** Creates a new observable map using a [SplayTreeMap]. */ |
58 ObservableMap.sorted() : _map = new SplayTreeMap<K, V>(); | 56 ObservableMap.sorted() : _map = new SplayTreeMap<K, V>(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 bool containsKey(Object key) => _map.containsKey(key); | 95 bool containsKey(Object key) => _map.containsKey(key); |
98 | 96 |
99 V operator [](Object key) => _map[key]; | 97 V operator [](Object key) => _map[key]; |
100 | 98 |
101 void operator []=(K key, V value) { | 99 void operator []=(K key, V value) { |
102 int len = _map.length; | 100 int len = _map.length; |
103 V oldValue = _map[key]; | 101 V oldValue = _map[key]; |
104 _map[key] = value; | 102 _map[key] = value; |
105 if (hasObservers) { | 103 if (hasObservers) { |
106 if (len != _map.length) { | 104 if (len != _map.length) { |
107 notifyPropertyChange(_LENGTH, len, _map.length); | 105 notifyPropertyChange(#length, len, _map.length); |
108 notifyChange(new MapChangeRecord(key, isInsert: true)); | 106 notifyChange(new MapChangeRecord(key, isInsert: true)); |
109 } else if (!identical(oldValue, value)) { | 107 } else if (!identical(oldValue, value)) { |
110 notifyChange(new MapChangeRecord(key)); | 108 notifyChange(new MapChangeRecord(key)); |
111 } | 109 } |
112 } | 110 } |
113 } | 111 } |
114 | 112 |
115 void addAll(Map<K, V> other) { | 113 void addAll(Map<K, V> other) { |
116 other.forEach((K key, V value) { this[key] = value; }); | 114 other.forEach((K key, V value) { this[key] = value; }); |
117 } | 115 } |
118 | 116 |
119 V putIfAbsent(K key, V ifAbsent()) { | 117 V putIfAbsent(K key, V ifAbsent()) { |
120 int len = _map.length; | 118 int len = _map.length; |
121 V result = _map.putIfAbsent(key, ifAbsent); | 119 V result = _map.putIfAbsent(key, ifAbsent); |
122 if (hasObservers && len != _map.length) { | 120 if (hasObservers && len != _map.length) { |
123 notifyPropertyChange(_LENGTH, len, _map.length); | 121 notifyPropertyChange(#length, len, _map.length); |
124 notifyChange(new MapChangeRecord(key, isInsert: true)); | 122 notifyChange(new MapChangeRecord(key, isInsert: true)); |
125 } | 123 } |
126 return result; | 124 return result; |
127 } | 125 } |
128 | 126 |
129 V remove(Object key) { | 127 V remove(Object key) { |
130 int len = _map.length; | 128 int len = _map.length; |
131 V result = _map.remove(key); | 129 V result = _map.remove(key); |
132 if (hasObservers && len != _map.length) { | 130 if (hasObservers && len != _map.length) { |
133 notifyChange(new MapChangeRecord(key, isRemove: true)); | 131 notifyChange(new MapChangeRecord(key, isRemove: true)); |
134 notifyPropertyChange(_LENGTH, len, _map.length); | 132 notifyPropertyChange(#length, len, _map.length); |
135 } | 133 } |
136 return result; | 134 return result; |
137 } | 135 } |
138 | 136 |
139 void clear() { | 137 void clear() { |
140 int len = _map.length; | 138 int len = _map.length; |
141 if (hasObservers && len > 0) { | 139 if (hasObservers && len > 0) { |
142 _map.forEach((key, value) { | 140 _map.forEach((key, value) { |
143 notifyChange(new MapChangeRecord(key, isRemove: true)); | 141 notifyChange(new MapChangeRecord(key, isRemove: true)); |
144 }); | 142 }); |
145 notifyPropertyChange(_LENGTH, len, 0); | 143 notifyPropertyChange(#length, len, 0); |
146 } | 144 } |
147 _map.clear(); | 145 _map.clear(); |
148 } | 146 } |
149 | 147 |
150 void forEach(void f(K key, V value)) => _map.forEach(f); | 148 void forEach(void f(K key, V value)) => _map.forEach(f); |
151 | 149 |
152 String toString() => Maps.mapToString(this); | 150 String toString() => Maps.mapToString(this); |
153 } | 151 } |
OLD | NEW |