|
@@ -131,8 +131,8 @@ class State {
|
|
updateTree(tree: StateTree | StateBuilder, options?: Partial<State.UpdateOptions>): Task<any> {
|
|
updateTree(tree: StateTree | StateBuilder, options?: Partial<State.UpdateOptions>): Task<any> {
|
|
return Task.create('Update Tree', async taskCtx => {
|
|
return Task.create('Update Tree', async taskCtx => {
|
|
let updated = false;
|
|
let updated = false;
|
|
|
|
+ const ctx = this.updateTreeAndCreateCtx(tree, taskCtx, options);
|
|
try {
|
|
try {
|
|
- const ctx = this.updateTreeAndCreateCtx(tree, taskCtx, options);
|
|
|
|
updated = await update(ctx);
|
|
updated = await update(ctx);
|
|
if (StateBuilder.isTo(tree)) {
|
|
if (StateBuilder.isTo(tree)) {
|
|
const cell = this.select(tree.ref)[0];
|
|
const cell = this.select(tree.ref)[0];
|
|
@@ -140,6 +140,10 @@ class State {
|
|
}
|
|
}
|
|
} finally {
|
|
} finally {
|
|
if (updated) this.events.changed.next();
|
|
if (updated) this.events.changed.next();
|
|
|
|
+
|
|
|
|
+ for (const ref of ctx.stateChanges) {
|
|
|
|
+ this.events.cell.stateUpdated.next({ state: this, ref, cellState: this.tree.cellStates.get(ref) });
|
|
|
|
+ }
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
@@ -161,6 +165,7 @@ class State {
|
|
transformCache: this.transformCache,
|
|
transformCache: this.transformCache,
|
|
|
|
|
|
results: [],
|
|
results: [],
|
|
|
|
+ stateChanges: [],
|
|
|
|
|
|
options: { ...StateUpdateDefaultOptions, ...options },
|
|
options: { ...StateUpdateDefaultOptions, ...options },
|
|
|
|
|
|
@@ -239,6 +244,7 @@ interface UpdateContext {
|
|
transformCache: Map<Ref, unknown>,
|
|
transformCache: Map<Ref, unknown>,
|
|
|
|
|
|
results: UpdateNodeResult[],
|
|
results: UpdateNodeResult[],
|
|
|
|
+ stateChanges: StateTransform.Ref[],
|
|
|
|
|
|
// suppress timing messages
|
|
// suppress timing messages
|
|
options: State.UpdateOptions,
|
|
options: State.UpdateOptions,
|
|
@@ -347,7 +353,6 @@ async function update(ctx: UpdateContext) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
return deletes.length > 0 || roots.length > 0 || ctx.changed;
|
|
return deletes.length > 0 || roots.length > 0 || ctx.changed;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -378,12 +383,16 @@ function findDeletes(ctx: UpdateContext): Ref[] {
|
|
return deleteCtx.deletes;
|
|
return deleteCtx.deletes;
|
|
}
|
|
}
|
|
|
|
|
|
-function syncStatesVisitor(n: StateTransform, tree: StateTree, oldState: StateTree.CellStates) {
|
|
|
|
- if (!oldState.has(n.ref)) return;
|
|
|
|
- (tree as TransientTree).updateCellState(n.ref, oldState.get(n.ref));
|
|
|
|
|
|
+function syncStatesVisitor(n: StateTransform, tree: StateTree, ctx: { oldState: StateTree.CellStates, newState: StateTree.CellStates, changes: StateTransform.Ref[] }) {
|
|
|
|
+ if (!ctx.oldState.has(n.ref)) return;
|
|
|
|
+ const changed = StateObjectCell.isStateChange(ctx.oldState.get(n.ref)!, ctx.newState.get(n.ref)!);
|
|
|
|
+ (tree as TransientTree).updateCellState(n.ref, ctx.newState.get(n.ref));
|
|
|
|
+ if (changed) {
|
|
|
|
+ ctx.changes.push(n.ref);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
function syncStates(ctx: UpdateContext) {
|
|
function syncStates(ctx: UpdateContext) {
|
|
- StateTree.doPreOrder(ctx.tree, ctx.tree.root, ctx.oldTree.cellStates, syncStatesVisitor);
|
|
|
|
|
|
+ StateTree.doPreOrder(ctx.tree, ctx.tree.root, { newState: ctx.tree.cellStates, oldState: ctx.oldTree.cellStates, changes: ctx.stateChanges }, syncStatesVisitor);
|
|
}
|
|
}
|
|
|
|
|
|
function setCellStatus(ctx: UpdateContext, ref: Ref, status: StateObjectCell.Status, errorText?: string) {
|
|
function setCellStatus(ctx: UpdateContext, ref: Ref, status: StateObjectCell.Status, errorText?: string) {
|