]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.structural.synchronization/src/org/simantics/structural/synchronization/base/SynchronizationEventHandlerBase.java
APIs for skipping state restoration for non-undo synchronization events
[simantics/platform.git] / bundles / org.simantics.structural.synchronization / src / org / simantics / structural / synchronization / base / SynchronizationEventHandlerBase.java
index a6efeefb2534bc402c25cfc671705ccbb6ad0cbb..5f8334398fe9ba99d896b9798ef195f20c5c059a 100644 (file)
@@ -56,6 +56,13 @@ public abstract class SynchronizationEventHandlerBase<T extends ComponentBase<T>
      */
     THashSet<T> potentiallyUpdatedComponents = new THashSet<>();
 
+    /**
+     * Is this potentially an undo/redo-related synchronization?
+     * 
+     * Default is true for backwards compatibility.
+     */
+    protected boolean isUndo = true;
+
     public SynchronizationEventHandlerBase(Solver solver, ReferenceResolverBase<T> resolver, SolverNameUtil nameUtil,
             ComponentFactory<T> componentFactory, ModuleUpdaterFactoryBase<T> moduleUpdaterFactory, MappingBase<T> mapping) {
         this.solver = solver;
@@ -66,6 +73,19 @@ public abstract class SynchronizationEventHandlerBase<T extends ComponentBase<T>
         this.resolver = resolver;
     }
     
+    /**
+     * Mark the undo/redo status of this handler.
+     * 
+     * Set 'isUndo' to false when processing a normal synchronization and true when
+     * processing an undo/redo.
+     * 
+     * When 'isUndo' is false, loading of component solver state from the state undo context
+     * is skipped for added components.
+     */
+    public void setAsUndo(boolean isUndo) {
+        this.isUndo = isUndo;
+    }
+
     @Override
     public void beginSynchronization() {
         if(TRACE_EVENTS) {
@@ -201,10 +221,14 @@ public abstract class SynchronizationEventHandlerBase<T extends ComponentBase<T>
 
                     // TODO these two lines can be removed when IncludedInSimulation -property is given to all composites
                     if(component.getParent() != null) {
-                       String parentName = solver.getName(component.getParent().getModuleId());
-                       solver.includeSubprocess(parentName, subprocessName);
-                       component.solverComponentName = subprocessName;
-                       solverComponentNameToComponent.put(subprocessName, component);
+                        int nearestParentId = getNearestParentComponentId(component);
+                        if (nearestParentId <= 0) {
+                            throw new SynchronizationException("Could not find parent with non-zero component id from Component("+name+", " + (component != null ? component.uid : "null") + "," + typeId + ")");
+                        }
+                        String parentName = solver.getName(nearestParentId);
+                        solver.includeSubprocess(parentName, subprocessName);
+                        component.solverComponentName = subprocessName;
+                        solverComponentNameToComponent.put(subprocessName, component);
                     }
                     
                     if(updater.isComposite) {
@@ -248,7 +272,7 @@ public abstract class SynchronizationEventHandlerBase<T extends ComponentBase<T>
                     if(oldChildMap != null)
                         for(T component : oldChildMap.values()) {
                             component.clearParent();
-                            mapping.addPendingRemoval(component);
+                            addPendingRemoval(component);
                         }
                 }
                 // Alternative implementation when uids are not available.
@@ -275,7 +299,7 @@ public abstract class SynchronizationEventHandlerBase<T extends ComponentBase<T>
                     if(oldChildMap != null)
                         for(T component : oldChildMap.values()) {
                             component.clearParent();
-                            mapping.addPendingRemoval(component);
+                            addPendingRemoval(component);
                         }
                 }
 
@@ -307,14 +331,16 @@ public abstract class SynchronizationEventHandlerBase<T extends ComponentBase<T>
                     else {
                         component.attached = false;
                         context.setModuleName(nameUtil.getFreshName(parentSolverComponentName, name));
-                        context.addPostUpdateAction(new Runnable() {
-                            @Override
-                            public void run() {
-                                context.stateLoadedFromUndo = mapping.undoContext.loadState(solver,
-                                        context.component.componentId, 
-                                        context.component.uid);
-                            }
-                        });
+                        if (isUndo) {
+                            context.addPostUpdateAction(new Runnable() {
+                                @Override
+                                public void run() {
+                                    context.stateLoadedFromUndo = mapping.undoContext.loadState(solver,
+                                            context.component.componentId, 
+                                            context.component.uid);
+                                }
+                            });
+                        }
                         updater.create(context, properties, connections);
                         solverComponentNameToComponent.put(context.getModuleName(), component);
                     }
@@ -334,6 +360,23 @@ public abstract class SynchronizationEventHandlerBase<T extends ComponentBase<T>
         }
     }
 
+    private static int getNearestParentComponentId(ComponentBase<?> component) {
+        ComponentBase<?> parent = component.getParent();
+        while (parent != null) {
+            int pid = parent.getModuleId();
+            if (pid > 0)
+                return pid;
+            parent = parent.getParent();
+        }
+        return -1;
+    }
+
+    protected void addPendingRemoval(T component) {
+        if (TRACE_EVENTS)
+            System.out.println("addPendingRemoval(" + component.componentId + " : " + component.solverComponentName + ")");
+        mapping.addPendingRemoval(component);
+    }
+
     private String getSubprocessName(String name,
             Collection<SerializedVariable> properties) {
         for(SerializedVariable property : properties)