From 8a7c5f192c3bacba9c7924a1b858e5e92c495d43 Mon Sep 17 00:00:00 2001
From: David Sehnal <david.sehnal@gmail.com>
Date: Wed, 6 Mar 2019 13:01:12 +0100
Subject: [PATCH] mol-state: improved cell state transition

---
 src/mol-state/state.ts          | 41 ++++++++++++++++++++++-----------
 src/mol-state/tree/transient.ts |  4 ++++
 2 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/src/mol-state/state.ts b/src/mol-state/state.ts
index 4da90c905..0269c30c1 100644
--- a/src/mol-state/state.ts
+++ b/src/mol-state/state.ts
@@ -296,15 +296,16 @@ async function update(ctx: UpdateContext) {
         roots = findUpdateRoots(ctx.cells, ctx.tree);
     }
 
+    let newCellStates: StateTree.CellStates;
+    if (!ctx.editInfo) {
+        newCellStates = ctx.tree.cellStatesSnapshot();
+        syncOldStates(ctx);
+    }
+
     // Init empty cells where not present
     // this is done in "pre order", meaning that "parents" will be created 1st.
     const addedCells = initCells(ctx, roots);
 
-    // Ensure cell states stay consistent
-    if (!ctx.editInfo) {
-        syncStates(ctx);
-    }
-
     // Notify additions of new cells.
     for (const cell of addedCells) {
         ctx.parent.events.cell.created.next({ state: ctx.parent, ref: cell.transform.ref, cell });
@@ -327,6 +328,11 @@ async function update(ctx: UpdateContext) {
         await updateSubtree(ctx, root);
     }
 
+    // Sync cell states
+    if (!ctx.editInfo) {
+        syncNewStates(ctx, newCellStates!);
+    }
+
     let newCurrent: StateTransform.Ref | undefined = ctx.newCurrent;
     // Raise object updated events
     for (const update of ctx.results) {
@@ -386,16 +392,25 @@ function findDeletes(ctx: UpdateContext): Ref[] {
     return deleteCtx.deletes;
 }
 
-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 syncOldStatesVisitor(n: StateTransform, tree: StateTree, oldState: StateTree.CellStates) {
+    if (oldState.has(n.ref)) {
+        (tree as TransientTree).updateCellState(n.ref, oldState.get(n.ref));
+    }
+}
+function syncOldStates(ctx: UpdateContext) {
+    StateTree.doPreOrder(ctx.tree, ctx.tree.root, ctx.oldTree.cellStates, syncOldStatesVisitor);
+}
+
+function syncNewStatesVisitor(n: StateTransform, tree: StateTree, ctx: { newState: StateTree.CellStates, changes: StateTransform.Ref[] }) {
+    if (ctx.newState.has(n.ref)) {
+        const changed = (tree as TransientTree).updateCellState(n.ref, ctx.newState.get(n.ref));
+        if (changed) {
+            ctx.changes.push(n.ref);
+        }
     }
 }
-function syncStates(ctx: UpdateContext) {
-    StateTree.doPreOrder(ctx.tree, ctx.tree.root, { newState: ctx.tree.cellStates, oldState: ctx.oldTree.cellStates, changes: ctx.stateChanges }, syncStatesVisitor);
+function syncNewStates(ctx: UpdateContext, newState: StateTree.CellStates) {
+    StateTree.doPreOrder(ctx.tree, ctx.tree.root, { newState, changes: ctx.stateChanges }, syncNewStatesVisitor);
 }
 
 function setCellStatus(ctx: UpdateContext, ref: Ref, status: StateObjectCell.Status, errorText?: string) {
diff --git a/src/mol-state/tree/transient.ts b/src/mol-state/tree/transient.ts
index 571d914c3..a48e8e663 100644
--- a/src/mol-state/tree/transient.ts
+++ b/src/mol-state/tree/transient.ts
@@ -49,6 +49,10 @@ class TransientTree implements StateTree {
 
     get root() { return this.transforms.get(StateTransform.RootRef)! }
 
+    cellStatesSnapshot() {
+        return this.cellStates.asImmutable();
+    }
+
     asTransient() {
         return this.asImmutable().asTransient();
     }
-- 
GitLab