| 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 library barback.asset_node; | 5 library barback.asset_node; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'asset.dart'; | 9 import 'asset.dart'; |
| 10 import 'asset_id.dart'; | 10 import 'asset_id.dart'; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 /// The current state of the asset node. | 43 /// The current state of the asset node. |
| 44 AssetState get state => _state; | 44 AssetState get state => _state; |
| 45 AssetState _state; | 45 AssetState _state; |
| 46 | 46 |
| 47 /// The concrete asset that this node represents. | 47 /// The concrete asset that this node represents. |
| 48 /// | 48 /// |
| 49 /// This is null unless [state] is [AssetState.AVAILABLE]. | 49 /// This is null unless [state] is [AssetState.AVAILABLE]. |
| 50 Asset get asset => _asset; | 50 Asset get asset => _asset; |
| 51 Asset _asset; | 51 Asset _asset; |
| 52 | 52 |
| 53 /// The callback to be called to notify this asset node's creator that the |
| 54 /// concrete asset should be generated. |
| 55 /// |
| 56 /// This is null for non-lazy asset nodes (see [AssetNodeController.lazy]). |
| 57 /// Once this is called, it's set to null and [this] is no longer considered |
| 58 /// lazy. |
| 59 Function _lazyCallback; |
| 60 |
| 53 /// A broadcast stream that emits an event whenever the node changes state. | 61 /// A broadcast stream that emits an event whenever the node changes state. |
| 54 /// | 62 /// |
| 55 /// This stream is synchronous to ensure that when a source asset is modified | 63 /// This stream is synchronous to ensure that when a source asset is modified |
| 56 /// or removed, the appropriate portion of the asset graph is dirtied before | 64 /// or removed, the appropriate portion of the asset graph is dirtied before |
| 57 /// any [Barback.getAssetById] calls emit newly-incorrect values. | 65 /// any [Barback.getAssetById] calls emit newly-incorrect values. |
| 58 Stream<AssetState> get onStateChange => _stateChangeController.stream; | 66 Stream<AssetState> get onStateChange => _stateChangeController.stream; |
| 59 | 67 |
| 60 /// This is synchronous so that a source being updated will always be | 68 /// This is synchronous so that a source being updated will always be |
| 61 /// propagated through the build graph before anything that depends on it is | 69 /// propagated through the build graph before anything that depends on it is |
| 62 /// requested. | 70 /// requested. |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 } | 139 } |
| 132 | 140 |
| 133 AssetNode._(this.id, this._transform, this._origin) | 141 AssetNode._(this.id, this._transform, this._origin) |
| 134 : _state = AssetState.DIRTY; | 142 : _state = AssetState.DIRTY; |
| 135 | 143 |
| 136 AssetNode._available(Asset asset, this._transform, this._origin) | 144 AssetNode._available(Asset asset, this._transform, this._origin) |
| 137 : id = asset.id, | 145 : id = asset.id, |
| 138 _asset = asset, | 146 _asset = asset, |
| 139 _state = AssetState.AVAILABLE; | 147 _state = AssetState.AVAILABLE; |
| 140 | 148 |
| 141 String toString() => "$state asset $id"; | 149 AssetNode._lazy(this.id, this._transform, this._origin, this._lazyCallback) |
| 150 : _state = AssetState.DIRTY; |
| 151 |
| 152 /// If [this] is lazy, force it to generate a concrete asset; otherwise, do |
| 153 /// nothing. |
| 154 /// |
| 155 /// See [AssetNodeController.lazy]. |
| 156 void force() { |
| 157 if (_origin != null) { |
| 158 _origin.force(); |
| 159 } else if (_lazyCallback != null) { |
| 160 _lazyCallback(); |
| 161 _lazyCallback = null; |
| 162 } |
| 163 } |
| 164 |
| 165 String toString() => |
| 166 "$state${_lazyCallback == null ? '' : ' lazy'} asset $id"; |
| 142 } | 167 } |
| 143 | 168 |
| 144 /// The controller for an [AssetNode]. | 169 /// The controller for an [AssetNode]. |
| 145 /// | 170 /// |
| 146 /// This controls which state the node is in. | 171 /// This controls which state the node is in. |
| 147 class AssetNodeController { | 172 class AssetNodeController { |
| 148 final AssetNode node; | 173 final AssetNode node; |
| 149 | 174 |
| 150 /// Creates a controller for a dirty node. | 175 /// Creates a controller for a dirty node. |
| 151 AssetNodeController(AssetId id, [TransformNode transform]) | 176 AssetNodeController(AssetId id, [TransformNode transform]) |
| 152 : node = new AssetNode._(id, transform, null); | 177 : node = new AssetNode._(id, transform, null); |
| 153 | 178 |
| 154 /// Creates a controller for an available node with the given concrete | 179 /// Creates a controller for an available node with the given concrete |
| 155 /// [asset]. | 180 /// [asset]. |
| 156 AssetNodeController.available(Asset asset, [TransformNode transform]) | 181 AssetNodeController.available(Asset asset, [TransformNode transform]) |
| 157 : node = new AssetNode._available(asset, transform, null); | 182 : node = new AssetNode._available(asset, transform, null); |
| 158 | 183 |
| 184 /// Creates a controller for a lazy node. |
| 185 /// |
| 186 /// For the most part, this node works like any other dirty node. However, the |
| 187 /// owner of its controller isn't expected to do the work to make it available |
| 188 /// as soon as possible like they would for a non-lazy node. Instead, when its |
| 189 /// value is needed, [callback] will fire to indicate that it should be made |
| 190 /// available as soon as possible. |
| 191 /// |
| 192 /// [callback] is guaranteed to only fire once. |
| 193 AssetNodeController.lazy(AssetId id, void callback(), |
| 194 [TransformNode transform]) |
| 195 : node = new AssetNode._lazy(id, transform, null, callback); |
| 196 |
| 159 /// Creates a controller for a node whose initial state matches the current | 197 /// Creates a controller for a node whose initial state matches the current |
| 160 /// state of [node]. | 198 /// state of [node]. |
| 161 /// | 199 /// |
| 162 /// [AssetNode.origin] of the returned node will automatically be set to | 200 /// [AssetNode.origin] of the returned node will automatically be set to |
| 163 /// `node.origin`. | 201 /// `node.origin`. |
| 202 /// |
| 203 /// If [node] is lazy, the returned node will also be lazy. |
| 164 AssetNodeController.from(AssetNode node) | 204 AssetNodeController.from(AssetNode node) |
| 165 : node = new AssetNode._(node.id, node.transform, node.origin) { | 205 : node = new AssetNode._(node.id, node.transform, node.origin) { |
| 166 if (node.state.isAvailable) { | 206 if (node.state.isAvailable) { |
| 167 setAvailable(node.asset); | 207 setAvailable(node.asset); |
| 168 } else if (node.state.isRemoved) { | 208 } else if (node.state.isRemoved) { |
| 169 setRemoved(); | 209 setRemoved(); |
| 170 } | 210 } |
| 171 } | 211 } |
| 172 | 212 |
| 173 /// Marks the node as [AssetState.DIRTY]. | 213 /// Marks the node as [AssetState.DIRTY]. |
| 174 void setDirty() { | 214 void setDirty() { |
| 175 assert(node._state != AssetState.REMOVED); | 215 assert(node._state != AssetState.REMOVED); |
| 176 node._state = AssetState.DIRTY; | 216 node._state = AssetState.DIRTY; |
| 177 node._asset = null; | 217 node._asset = null; |
| 218 node._lazyCallback = null; |
| 178 node._stateChangeController.add(AssetState.DIRTY); | 219 node._stateChangeController.add(AssetState.DIRTY); |
| 179 } | 220 } |
| 180 | 221 |
| 181 /// Marks the node as [AssetState.REMOVED]. | 222 /// Marks the node as [AssetState.REMOVED]. |
| 182 /// | 223 /// |
| 183 /// Once a node is marked as removed, it can't be marked as any other state. | 224 /// Once a node is marked as removed, it can't be marked as any other state. |
| 184 /// If a new asset is created with the same id, it will get a new node. | 225 /// If a new asset is created with the same id, it will get a new node. |
| 185 void setRemoved() { | 226 void setRemoved() { |
| 186 assert(node._state != AssetState.REMOVED); | 227 assert(node._state != AssetState.REMOVED); |
| 187 node._state = AssetState.REMOVED; | 228 node._state = AssetState.REMOVED; |
| 188 node._asset = null; | 229 node._asset = null; |
| 230 node._lazyCallback = null; |
| 189 node._stateChangeController.add(AssetState.REMOVED); | 231 node._stateChangeController.add(AssetState.REMOVED); |
| 190 } | 232 } |
| 191 | 233 |
| 192 /// Marks the node as [AssetState.AVAILABLE] with the given concrete [asset]. | 234 /// Marks the node as [AssetState.AVAILABLE] with the given concrete [asset]. |
| 193 /// | 235 /// |
| 194 /// It's an error to mark an already-available node as available. It should be | 236 /// It's an error to mark an already-available node as available. It should be |
| 195 /// marked as dirty first. | 237 /// marked as dirty first. |
| 196 void setAvailable(Asset asset) { | 238 void setAvailable(Asset asset) { |
| 197 assert(asset.id == node.id); | 239 assert(asset.id == node.id); |
| 198 assert(node._state != AssetState.REMOVED); | 240 assert(node._state != AssetState.REMOVED); |
| 199 assert(node._state != AssetState.AVAILABLE); | 241 assert(node._state != AssetState.AVAILABLE); |
| 200 node._state = AssetState.AVAILABLE; | 242 node._state = AssetState.AVAILABLE; |
| 201 node._asset = asset; | 243 node._asset = asset; |
| 244 node._lazyCallback = null; |
| 202 node._stateChangeController.add(AssetState.AVAILABLE); | 245 node._stateChangeController.add(AssetState.AVAILABLE); |
| 203 } | 246 } |
| 204 | 247 |
| 248 /// Marks the node as [AssetState.DIRTY] and lazy. |
| 249 /// |
| 250 /// Lazy nodes aren't expected to have their values generated until needed. |
| 251 /// Once it's necessary, [callback] will be called. [callback] is guaranteed |
| 252 /// to be called only once. |
| 253 /// |
| 254 /// See also [AssetNodeController.lazy]. |
| 255 void setLazy(void callback()) { |
| 256 assert(node._state != AssetState.REMOVED); |
| 257 node._state = AssetState.DIRTY; |
| 258 node._asset = null; |
| 259 node._lazyCallback = callback; |
| 260 node._stateChangeController.add(AssetState.DIRTY); |
| 261 } |
| 262 |
| 205 String toString() => "controller for $node"; | 263 String toString() => "controller for $node"; |
| 206 } | 264 } |
| 207 | 265 |
| 208 // TODO(nweiz): add an error state. | 266 // TODO(nweiz): add an error state. |
| 209 /// An enum of states that an [AssetNode] can be in. | 267 /// An enum of states that an [AssetNode] can be in. |
| 210 class AssetState { | 268 class AssetState { |
| 211 /// The node has a concrete asset loaded, available, and up-to-date. The asset | 269 /// The node has a concrete asset loaded, available, and up-to-date. The asset |
| 212 /// is accessible via [AssetNode.asset]. An asset can only be marked available | 270 /// is accessible via [AssetNode.asset]. An asset can only be marked available |
| 213 /// again from the [AssetState.DIRTY] state. | 271 /// again from the [AssetState.DIRTY] state. |
| 214 static final AVAILABLE = const AssetState._("available"); | 272 static final AVAILABLE = const AssetState._("available"); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 229 | 287 |
| 230 /// Whether this state is [AssetState.DIRTY]. | 288 /// Whether this state is [AssetState.DIRTY]. |
| 231 bool get isDirty => this == AssetState.DIRTY; | 289 bool get isDirty => this == AssetState.DIRTY; |
| 232 | 290 |
| 233 final String name; | 291 final String name; |
| 234 | 292 |
| 235 const AssetState._(this.name); | 293 const AssetState._(this.name); |
| 236 | 294 |
| 237 String toString() => name; | 295 String toString() => name; |
| 238 } | 296 } |
| OLD | NEW |