From: Marko Luukkainen Date: Mon, 19 Aug 2019 12:52:48 +0000 (+0300) Subject: Preventing synchronizing commits after undo / redo are mandatory X-Git-Tag: v1.43.0~216^2 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F17%2F3117%2F2;p=simantics%2F3d.git Preventing synchronizing commits after undo / redo are mandatory Allowing synchronizing commits with empty message and no undo point trash the undo history and prevent redo operations. Include scl folder in build.properties gitlab #24 Change-Id: I0af0cbf3be21a23ac4f8ed20a48881bef21465d2 --- diff --git a/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/common/AbstractVTKNodeMap.java b/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/common/AbstractVTKNodeMap.java index 6194ec82..b5a7dfe6 100644 --- a/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/common/AbstractVTKNodeMap.java +++ b/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/common/AbstractVTKNodeMap.java @@ -23,6 +23,7 @@ import java.util.Stack; import org.simantics.db.ReadGraph; import org.simantics.db.Session; +import org.simantics.db.UndoContext; import org.simantics.db.WriteGraph; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.common.request.WriteRequest; @@ -47,261 +48,273 @@ import vtk.vtkProp; public abstract class AbstractVTKNodeMap implements VTKNodeMap, IMappingListener, RenderListener, NodeListener, UndoRedoSupport.ChangeListener{ - private static final boolean DEBUG = false; - - protected Session session; - protected IMapping mapping; - protected VtkView view; - - protected MapList nodeToActor = new MapList(); - protected Map actorToNode = new HashMap(); + private static final boolean DEBUG = false; + + protected Session session; + protected IMapping mapping; + protected VtkView view; + + protected MapList nodeToActor = new MapList(); + protected Map actorToNode = new HashMap(); - protected ParentNode rootNode; - - protected UndoRedoSupport undoRedoSupport; - protected int undoOpCount = 0; - protected boolean runUndo = false; - public AbstractVTKNodeMap(Session session, IMapping mapping, VtkView view, ParentNode rootNode) { - this.session = session; - this.mapping = mapping; - this.view = view; - this.rootNode = rootNode; - view.addListener(this); - mapping.addMappingListener(this); - rootNode.addListener(this); - - undoRedoSupport = session.getService(UndoRedoSupport.class); - undoRedoSupport.subscribe(this); - try { - undoOpCount = undoRedoSupport.getUndoContext(session).getAll().size(); - } catch(DatabaseException e) { - e.printStackTrace(); - } - } - - - - protected abstract void addActor(E node); - protected abstract void removeActor(E node); - protected abstract void updateActor(E node,Set ids); - - public void repaint() { - view.refresh(); - } - - public void populate() { - for (E node : rootNode.getNodes()) { - receiveAdd(node, node.getParentRel(),true); - } - repaint(); - } - - @Override - public E getNode(vtkProp prop) { - return actorToNode.get(prop); - } - - @SuppressWarnings("unchecked") - @Override - public Collection getRenderObjects(INode node) { - return nodeToActor.getValues((E)node); - } - - @SuppressWarnings("unchecked") - @Override - public ParentNode getRootNode() { - return (ParentNode)rootNode; - } - - - - @Override - public boolean isChangeTracking() { - return changeTracking; - } - - @Override - public void setChangeTracking(boolean enabled) { - changeTracking = enabled; - } - - private boolean changeTracking = true; - - protected Object syncMutex = new Object(); - + protected ParentNode rootNode; + + protected UndoRedoSupport undoRedoSupport; + protected int undoOpCount = 0; + protected int redoOpCount = 0; + protected boolean runUndo = false; + protected boolean runRedo = false; + public AbstractVTKNodeMap(Session session, IMapping mapping, VtkView view, ParentNode rootNode) { + this.session = session; + this.mapping = mapping; + this.view = view; + this.rootNode = rootNode; + view.addListener(this); + mapping.addMappingListener(this); + rootNode.addListener(this); + + undoRedoSupport = session.getService(UndoRedoSupport.class); + undoRedoSupport.subscribe(this); + try { + UndoContext undoContext = undoRedoSupport.getUndoContext(session); + undoOpCount = undoContext.getAll().size(); + redoOpCount = undoContext.getRedoList().size(); + } catch(DatabaseException e) { + e.printStackTrace(); + } + } + + + + protected abstract void addActor(E node); + protected abstract void removeActor(E node); + protected abstract void updateActor(E node,Set ids); + + public void repaint() { + view.refresh(); + } + + public void populate() { + for (E node : rootNode.getNodes()) { + receiveAdd(node, node.getParentRel(),true); + } + repaint(); + } + + @Override + public E getNode(vtkProp prop) { + return actorToNode.get(prop); + } + + @SuppressWarnings("unchecked") + @Override + public Collection getRenderObjects(INode node) { + return nodeToActor.getValues((E)node); + } + + @SuppressWarnings("unchecked") + @Override + public ParentNode getRootNode() { + return (ParentNode)rootNode; + } + + + + @Override + public boolean isChangeTracking() { + return changeTracking; + } + + @Override + public void setChangeTracking(boolean enabled) { + changeTracking = enabled; + } + + private boolean changeTracking = true; + + protected Object syncMutex = new Object(); + - private List> added = new ArrayList>(); - private List> removed = new ArrayList>(); - //private List> updated = new ArrayList>(); - private MapSet updated = new MapSet.Hash(); + private List> added = new ArrayList>(); + private List> removed = new ArrayList>(); + private MapSet updated = new MapSet.Hash(); - private boolean rangeModified = false; - - @Override - public void onChanged() { - try { - int count = undoRedoSupport.getUndoContext(session).getAll().size(); - if (count < undoOpCount) { + private boolean rangeModified = false; + + @Override + public void onChanged() { + try { + UndoContext undoContext = undoRedoSupport.getUndoContext(session); + int ucount = undoContext.getAll().size(); + int rcount = undoContext.getRedoList().size(); + if (DEBUG) System.out.println("Previous U:" + undoOpCount +" R:" + redoOpCount +" Current U:"+ucount+" R:"+rcount); + if (ucount < undoOpCount) { runUndo = true; } else { runUndo = false; } - undoOpCount = count; - if (DEBUG) System.out.println("Undo " + runUndo); + if (!runUndo && rcount > 0) + runRedo = true; + else + runRedo = false; + undoOpCount = ucount; + redoOpCount = rcount; + + if (DEBUG) System.out.println("Undo " + runUndo + " Redo " + runRedo); } catch (DatabaseException e) { // TODO Auto-generated catch block e.printStackTrace(); } - - - } - - @SuppressWarnings("unchecked") - @Override - public void updateRenderObjectsFor(INode node) { - List toDelete = new ArrayList(); - view.lock(); - for (vtkProp prop : nodeToActor.getValues((E)node)) { - if (prop.GetVTKId() != 0) { - view.getRenderer().RemoveActor(prop); - //prop.Delete(); - toDelete.add(prop); - } - actorToNode.remove(prop); - } - view.unlock(); - nodeToActor.remove((E)node); - Collection coll = getActors((E)node); - if (coll == null) - return; - for (vtkProp prop : coll) { - nodeToActor.add((E)node,prop); - actorToNode.put(prop, (E)node); - toDelete.remove(prop); - } - for (vtkProp p : toDelete) - p.Delete(); - } - - protected abstract Collection getActors(E node); - - @SuppressWarnings("unchecked") - private void receiveAdd(E node, String id, boolean db) { - if (DEBUG) System.out.println("receiveAdd " + debugString(node) + " " + id + " " + db); - synchronized (syncMutex) { - for (Pair n : added) { - if (n.first.equals(node)) - return; - } - if (changeTracking) { - mapping.rangeModified((E)node.getParent()); - } - added.add(new Pair(node, id)); - rangeModified = true; - } - view.refresh(); - } - - @SuppressWarnings("unchecked") - private void receiveRemove(E node, String id, boolean db) { - if (DEBUG) System.out.println("receiveRemove " + debugString(node) + " " + id + " " + db); - synchronized (syncMutex) { - for (Pair n : removed) { - if (n.first.equals(node)) - return; - } - if (changeTracking && !db) - mapping.rangeModified((E)node.getParent()); - removed.add(new Pair(node, id)); - rangeModified = true; - } - view.refresh(); - } - - @SuppressWarnings("unchecked") - private void receiveUpdate(E node, String id, boolean db) { - if (DEBUG) System.out.println("receiveUpdate " + debugString(node) + " " + id + " " + db); - synchronized (syncMutex) { -// for (Pair n : updated) { -// if (n.first.equals(node)) -// return; -// } - if (changeTracking && !db) - mapping.rangeModified(node); - //updated.add(new Pair(node, id)); - updated.add(node, id); - rangeModified = true; - } - view.refresh(); - } - - private boolean graphUpdates = false; - private Set graphModified = new HashSet(); - - private boolean requestCommit = false; - private String commitMessage = null; - - @Override - public void commit(String message) { - requestCommit = true; - commitMessage = message; - } - - protected void doCommit() { - session.asyncRequest(new WriteRequest() { - - @Override - public void perform(WriteGraph graph) throws DatabaseException { - if (DEBUG) System.out.println("Commit " + commitMessage); - if (commitMessage != null) { - Layer0Utils.addCommentMetadata(graph, commitMessage); - graph.markUndoPoint(); - commitMessage = null; - } - commit(graph); - } - - }, new Callback() { - - @Override - public void run(DatabaseException parameter) { - if (parameter != null) - ExceptionUtils.logAndShowError("Cannot commit editor changes", parameter); - } - }); - } - - protected void commit(WriteGraph graph) throws DatabaseException { - synchronized(syncMutex) { - if (DEBUG) System.out.println("Commit"); - graphUpdates = true; - mapping.updateDomain(graph); - graphUpdates = false; - clearDeletes(); - if (DEBUG) System.out.println("Commit done"); - } - } - - - - @Override - public void domainModified() { - if (graphUpdates) - return; - if (DEBUG)System.out.println("domainModified"); - session.asyncRequest(new ReadRequest() { - - @SuppressWarnings("unchecked") - @Override - public void run(ReadGraph graph) throws DatabaseException { - update(graph); - } - }); - - } - - protected void reset(ReadGraph graph) throws MappingException { - if (DEBUG) System.out.println("Reset"); + + + } + + @SuppressWarnings("unchecked") + @Override + public void updateRenderObjectsFor(E node) { + List toDelete = new ArrayList(); + view.lock(); + for (vtkProp prop : nodeToActor.getValues((E)node)) { + if (prop.GetVTKId() != 0) { + view.getRenderer().RemoveActor(prop); + //prop.Delete(); + toDelete.add(prop); + } + actorToNode.remove(prop); + } + view.unlock(); + nodeToActor.remove((E)node); + Collection coll = getActors((E)node); + if (coll != null) { + for (vtkProp prop : coll) { + nodeToActor.add((E)node,prop); + actorToNode.put(prop, (E)node); + toDelete.remove(prop); + } + } + for (vtkProp p : toDelete) + p.Delete(); + } + + protected abstract Collection getActors(E node); + + @SuppressWarnings("unchecked") + private void receiveAdd(E node, String id, boolean db) { + if (DEBUG) System.out.println("receiveAdd " + debugString(node) + " " + id + " " + db); + synchronized (syncMutex) { + for (Pair n : added) { + if (n.first.equals(node)) + return; + } + if (changeTracking) { + mapping.rangeModified((E)node.getParent()); + } + added.add(new Pair(node, id)); + rangeModified = true; + } + view.refresh(); + } + + @SuppressWarnings("unchecked") + private void receiveRemove(E node, String id, boolean db) { + if (DEBUG) System.out.println("receiveRemove " + debugString(node) + " " + id + " " + db); + synchronized (syncMutex) { + for (Pair n : removed) { + if (n.first.equals(node)) + return; + } + if (changeTracking && !db) + mapping.rangeModified((E)node.getParent()); + removed.add(new Pair(node, id)); + rangeModified = true; + } + repaint(); + } + + @SuppressWarnings("unchecked") + private void receiveUpdate(E node, String id, boolean db) { + if (DEBUG) System.out.println("receiveUpdate " + debugString(node) + " " + id + " " + db); + synchronized (syncMutex) { +// for (Pair n : updated) { +// if (n.first.equals(node)) +// return; +// } + if (changeTracking && !db) + mapping.rangeModified(node); + //updated.add(new Pair(node, id)); + updated.add(node, id); + rangeModified = true; + } + repaint(); + } + + private boolean graphUpdates = false; + private Set graphModified = new HashSet(); + + private boolean requestCommit = false; + private String commitMessage = null; + + @Override + public void commit(String message) { + requestCommit = true; + commitMessage = message; + } + + protected void doCommit() { + session.asyncRequest(new WriteRequest() { + + @Override + public void perform(WriteGraph graph) throws DatabaseException { + if (DEBUG) System.out.println("Commit " + commitMessage); + if (commitMessage != null) { + Layer0Utils.addCommentMetadata(graph, commitMessage); + graph.markUndoPoint(); + commitMessage = null; + } + commit(graph); + } + + }, new Callback() { + + @Override + public void run(DatabaseException parameter) { + if (parameter != null) + ExceptionUtils.logAndShowError("Cannot commit editor changes", parameter); + } + }); + } + + protected void commit(WriteGraph graph) throws DatabaseException { + synchronized(syncMutex) { + if (DEBUG) System.out.println("Commit"); + graphUpdates = true; + mapping.updateDomain(graph); + graphUpdates = false; + clearDeletes(); + if (DEBUG) System.out.println("Commit done"); + } + } + + + + @Override + public void domainModified() { + if (graphUpdates) + return; + if (DEBUG)System.out.println("domainModified"); + session.asyncRequest(new ReadRequest() { + + @SuppressWarnings("unchecked") + @Override + public void run(ReadGraph graph) throws DatabaseException { + update(graph); + } + }); + + } + + protected void reset(ReadGraph graph) throws MappingException { + if (DEBUG) System.out.println("Reset"); synchronized (syncMutex) { graphUpdates = true; mapping.getRangeModified().clear(); @@ -311,78 +324,77 @@ public abstract class AbstractVTKNodeMap implements VTKNodeMap< graphModified.clear(); graphUpdates = false; } - } - - private boolean useFullSyncWithUndo = false; - - protected void update(ReadGraph graph) throws DatabaseException { - if (DEBUG) System.out.println("Graph update start"); - if (runUndo && useFullSyncWithUndo) { - reset(graph); - } else { - synchronized (syncMutex) { - graphUpdates = true; - for (Object domainObject : mapping.getDomainModified()) { - E rangeObject = mapping.get(domainObject); - if (rangeObject != null) - graphModified.add(rangeObject); - } - mapping.updateRange(graph); - graphModified.clear(); - syncDeletes(); - clearDeletes(); - graphUpdates = false; - } - } - - //if (mapping.isRangeModified() && !runUndo) // FIXME : redo? - if (mapping.isRangeModified()) - commit((String)null); - if (DEBUG) System.out.println("Graph update done"); - } - - @Override - public void rangeModified() { - //System.out.println("rangeModified"); + } + + private boolean useFullSyncWithUndo = false; + + protected void update(ReadGraph graph) throws DatabaseException { + if (DEBUG) System.out.println("Graph update start"); + if (runUndo && useFullSyncWithUndo) { + reset(graph); + } else { + synchronized (syncMutex) { + graphUpdates = true; + for (Object domainObject : mapping.getDomainModified()) { + E rangeObject = mapping.get(domainObject); + if (rangeObject != null) + graphModified.add(rangeObject); + } + mapping.updateRange(graph); + graphModified.clear(); + syncDeletes(); + clearDeletes(); + graphUpdates = false; + } + } + + if (mapping.isRangeModified() && !runUndo && !runRedo) + commit((String)null); + if (DEBUG) System.out.println("Graph update done"); + } + + @Override + public void rangeModified() { + //System.out.println("rangeModified"); - } - - @Override - public void postRender() { - // Commit changes if - // 1. Commit has been requested - // 2. There are no pending changes that should be processed in preRender() - if (requestCommit && !rangeModified) { // FIXME : not thread safe. - requestCommit = false; - doCommit(); - } - } - - // Reusable containers for data synchronisation - List> rem = new ArrayList>(); // Removed objects - List> add = new ArrayList>(); // Added objects - MapSet mod = new MapSet.Hash(); // Modified objects - Set propagation = new HashSet(); // Objects with propagated changes - Stack stack = new Stack(); // Stack for handling propagation - Set delete = Collections.synchronizedSet(new HashSet()); // Objects to be completely deleted - Set deleteUC = new HashSet(); - - @Override - public synchronized void preRender() { - updateCycle(); - } - - - /** - * When objects are removed (either from Java or Graph), after remove processing the Java objects remain in mapping cache. - * This causes problems with Undo and Redo, whcih the end up re-using the removed objects from mapping cache. - * - * This code here synchronizes removed and added objects to collect deletable objects. (a deletable object is one which is removed but not added). - * - */ - protected void syncDeletes() { - deleteUC.clear(); - for (Pair n : removed) { + } + + @Override + public void postRender() { + // Commit changes if + // 1. Commit has been requested + // 2. There are no pending changes that should be processed in preRender() + if (requestCommit && !rangeModified) { // FIXME : not thread safe. + requestCommit = false; + doCommit(); + } + } + + // Reusable containers for data synchronisation + List> rem = new ArrayList>(); // Removed objects + List> add = new ArrayList>(); // Added objects + MapSet mod = new MapSet.Hash(); // Modified objects + Set propagation = new HashSet(); // Objects with propagated changes + Stack stack = new Stack(); // Stack for handling propagation + Set delete = Collections.synchronizedSet(new HashSet()); // Objects to be completely deleted + Set deleteUC = new HashSet(); + + @Override + public synchronized void preRender() { + updateCycle(); + } + + + /** + * When objects are removed (either from Java or Graph), after remove processing the Java objects remain in mapping cache. + * This causes problems with Undo and Redo, whcih the end up re-using the removed objects from mapping cache. + * + * This code here synchronizes removed and added objects to collect deletable objects. (a deletable object is one which is removed but not added). + * + */ + protected void syncDeletes() { + deleteUC.clear(); + for (Pair n : removed) { deleteUC.add(n.first); } for (Pair n : added) { @@ -396,12 +408,12 @@ public abstract class AbstractVTKNodeMap implements VTKNodeMap< } delete.addAll(deleteUC); deleteUC.clear(); - } - - /** - * Clears deletable objects from mapping cache. - */ - protected void clearDeletes() { + } + + /** + * Clears deletable objects from mapping cache. + */ + protected void clearDeletes() { if (DEBUG && delete.size() > 0) System.out.println("Delete"); for (E n : delete) { if (DEBUG) System.out.println(debugString(n)); @@ -409,212 +421,212 @@ public abstract class AbstractVTKNodeMap implements VTKNodeMap< } delete.clear(); } - - protected String debugString(E n) { - return n + "@" + Integer.toHexString(n.hashCode()); - } - - @SuppressWarnings("unchecked") - protected void updateCycle() { - rem.clear(); - add.clear(); - mod.clear(); - propagation.clear(); - - - synchronized (syncMutex) { - rem.addAll(removed); - add.addAll(added); - for (E e : updated.getKeys()) { - for (String s : updated.getValues(e)) { - mod.add(e, s); - } - } - syncDeletes(); - removed.clear(); - added.clear(); - updated.clear(); - } - - for (Pair n : rem) { - stopListening(n.first); - removeActor(n.first); - } - - for (Pair n : add) { - addActor(n.first); - listen(n.first); - } - - for (E e : mod.getKeys()) { - Set ids = mod.getValues(e); - if (ids.contains(G3D.URIs.hasPosition) || ids.contains(G3D.URIs.hasOrientation)) { - if (!propagation.contains(e)) - propagation.add(e); - } - } + + protected String debugString(E n) { + return n + "@" + Integer.toHexString(n.hashCode()); + } + + @SuppressWarnings("unchecked") + protected void updateCycle() { + rem.clear(); + add.clear(); + mod.clear(); + propagation.clear(); + + + synchronized (syncMutex) { + rem.addAll(removed); + add.addAll(added); + for (E e : updated.getKeys()) { + for (String s : updated.getValues(e)) { + mod.add(e, s); + } + } + syncDeletes(); + removed.clear(); + added.clear(); + updated.clear(); + } + + for (Pair n : rem) { + stopListening(n.first); + removeActor(n.first); + } + + for (Pair n : add) { + addActor(n.first); + listen(n.first); + } + + for (E e : mod.getKeys()) { + Set ids = mod.getValues(e); + if (ids.contains(G3D.URIs.hasPosition) || ids.contains(G3D.URIs.hasOrientation)) { + if (!propagation.contains(e)) + propagation.add(e); + } + } - if (propagation.size() > 0) { - stack.clear(); - stack.addAll(propagation); - propagation.clear(); - while (!stack.isEmpty()) { - E node = stack.pop(); - if (propagation.contains(node)) - continue; - propagation.add(node); - for (NodeListener l : node.getListeners()) { - if (l == this) { - //changeTracking = false; - //l.propertyChanged(node, G3D.URIs.hasPosition); - //changeTracking = true; - } else { - l.propertyChanged(node, G3D.URIs.hasWorldPosition); - } - } - if (node instanceof ParentNode) { - stack.addAll(((ParentNode)node).getNodes()); - } - } - } - -// synchronized (syncMutex) { -// rem.addAll(removed); -// add.addAll(added); -// //mod.addAll(updated); -// for (E e : updated.getKeys()) { -// for (String s : updated.getValues(e)) -// mod.add(e, s); -// } -// -// removed.clear(); -// added.clear(); -// updated.clear(); -// } - - for (E e : mod.getKeys()) { - Set ids = mod.getValues(e); - updateActor(e,ids); - } - - - for (Pair n : rem) { - for (NodeListener l : nodeListeners) - l.nodeRemoved(null, n.first, n.second); - } - for (Pair n : add) { - for (NodeListener l : nodeListeners) - l.nodeAdded(n.first.getParent(), n.first, n.second); - } -// for (Pair n : mod) { -// for (NodeListener l : nodeListeners) -// l.propertyChanged(n.first, n.second); -// } - for (E e : mod.getKeys()) { - for (NodeListener l : nodeListeners) - for (String s : mod.getValues(e)) - l.propertyChanged(e, s); - } - - synchronized (syncMutex) { - if (added.isEmpty() && removed.isEmpty() && updated.getKeys().size() == 0) - rangeModified = false; - } - } - - @SuppressWarnings("unchecked") - private void listen(INode node) { - node.addListener(this); - if (node instanceof ParentNode) { - ParentNode parentNode = (ParentNode)node; - for (INode n : parentNode.getNodes()) - listen(n); - } - } - - private void stopListening(INode node) { - node.removeListener(this); - if (node instanceof ParentNode) { - @SuppressWarnings("unchecked") - ParentNode parentNode = (ParentNode)node; - for (INode n : parentNode.getNodes()) - stopListening(n); - } - } - - @SuppressWarnings("unchecked") - @Override - public void propertyChanged(INode node, String id) { - //receiveUpdate((E)node, id, graphUpdates); - receiveUpdate((E)node, id, graphModified.contains(node)); - - } - - @SuppressWarnings("unchecked") - @Override - public void nodeAdded(ParentNode node, INode child, - String rel) { - if (DEBUG) System.out.println("Node added " + child + " parent " + node); - //receiveAdd((E)child, rel ,graphUpdates); - receiveAdd((E)child, rel ,graphModified.contains(node)); - - } - - @SuppressWarnings("unchecked") - @Override - public void nodeRemoved(ParentNode node, INode child, - String rel) { - if (DEBUG) System.out.println("Node removed " + child + " parent " + node); - //receiveRemove((E)child, rel, graphUpdates); - receiveRemove((E)child, rel, graphModified.contains(node)); - - //FIXME : sometimes removed structural models cause ObjMap to add their children again. - // removing the listener here prevents corruption of visual model, but better fix is needed. - stopListening(child); - } - - @Override - public void delete() { - if (undoRedoSupport != null) - undoRedoSupport.cancel(this); + if (propagation.size() > 0) { + stack.clear(); + stack.addAll(propagation); + propagation.clear(); + while (!stack.isEmpty()) { + E node = stack.pop(); + if (propagation.contains(node)) + continue; + propagation.add(node); + for (NodeListener l : node.getListeners()) { + if (l == this) { + //changeTracking = false; + //l.propertyChanged(node, G3D.URIs.hasPosition); + //changeTracking = true; + } else { + l.propertyChanged(node, G3D.URIs.hasWorldPosition); + } + } + if (node instanceof ParentNode) { + stack.addAll(((ParentNode)node).getNodes()); + } + } + } + +// synchronized (syncMutex) { +// rem.addAll(removed); +// add.addAll(added); +// //mod.addAll(updated); +// for (E e : updated.getKeys()) { +// for (String s : updated.getValues(e)) +// mod.add(e, s); +// } +// +// removed.clear(); +// added.clear(); +// updated.clear(); +// } - changeTracking = false; - view.removeListener(this); - mapping.removeMappingListener(this); + for (E e : mod.getKeys()) { + Set ids = mod.getValues(e); + updateActor(e,ids); + } + + + for (Pair n : rem) { + for (NodeListener l : nodeListeners) + l.nodeRemoved(null, n.first, n.second); + } + for (Pair n : add) { + for (NodeListener l : nodeListeners) + l.nodeAdded(n.first.getParent(), n.first, n.second); + } +// for (Pair n : mod) { +// for (NodeListener l : nodeListeners) +// l.propertyChanged(n.first, n.second); +// } + for (E e : mod.getKeys()) { + for (NodeListener l : nodeListeners) + for (String s : mod.getValues(e)) + l.propertyChanged(e, s); + } + + synchronized (syncMutex) { + if (added.isEmpty() && removed.isEmpty() && updated.getKeys().size() == 0) + rangeModified = false; + } + } + + @SuppressWarnings("unchecked") + private void listen(INode node) { + node.addListener(this); + if (node instanceof ParentNode) { + ParentNode parentNode = (ParentNode)node; + for (INode n : parentNode.getNodes()) + listen(n); + } + } + + private void stopListening(INode node) { + node.removeListener(this); + if (node instanceof ParentNode) { + @SuppressWarnings("unchecked") + ParentNode parentNode = (ParentNode)node; + for (INode n : parentNode.getNodes()) + stopListening(n); + } + } + + @SuppressWarnings("unchecked") + @Override + public void propertyChanged(INode node, String id) { + //receiveUpdate((E)node, id, graphUpdates); + receiveUpdate((E)node, id, graphModified.contains(node)); + + } + + @SuppressWarnings("unchecked") + @Override + public void nodeAdded(ParentNode node, INode child, + String rel) { + if (DEBUG) System.out.println("Node added " + child + " parent " + node); + //receiveAdd((E)child, rel ,graphUpdates); + receiveAdd((E)child, rel ,graphModified.contains(node)); + + } + + @SuppressWarnings("unchecked") + @Override + public void nodeRemoved(ParentNode node, INode child, + String rel) { + if (DEBUG) System.out.println("Node removed " + child + " parent " + node); + //receiveRemove((E)child, rel, graphUpdates); + receiveRemove((E)child, rel, graphModified.contains(node)); + + //FIXME : sometimes removed structural models cause ObjMap to add their children again. + // removing the listener here prevents corruption of visual model, but better fix is needed. + stopListening(child); + } + + @Override + public void delete() { + if (undoRedoSupport != null) + undoRedoSupport.cancel(this); + + changeTracking = false; + view.removeListener(this); + mapping.removeMappingListener(this); - List nodes = new ArrayList(nodeToActor.getKeySize()); - nodes.addAll(nodeToActor.getKeys()); - for (E node : nodes) { - node.removeListener(this); - removeActor(node); - node.cleanup(); - } - for (vtkProp prop : actorToNode.keySet()) { - if (prop.GetVTKId() != 0) - prop.Delete(); - } - actorToNode.clear(); - nodeToActor.clear(); - - } - - - private List nodeListeners = new ArrayList(); - @Override - public void addListener(NodeListener listener) { - nodeListeners.add(listener); - - } - - @Override - public void removeListener(NodeListener listener) { - nodeListeners.remove(listener); - - } - - public IMapping getMapping() { - return mapping; - } - - + List nodes = new ArrayList(nodeToActor.getKeySize()); + nodes.addAll(nodeToActor.getKeys()); + for (E node : nodes) { + node.removeListener(this); + removeActor(node); + node.cleanup(); + } + for (vtkProp prop : actorToNode.keySet()) { + if (prop.GetVTKId() != 0) + prop.Delete(); + } + actorToNode.clear(); + nodeToActor.clear(); + + } + + + private List nodeListeners = new ArrayList(); + @Override + public void addListener(NodeListener listener) { + nodeListeners.add(listener); + + } + + @Override + public void removeListener(NodeListener listener) { + nodeListeners.remove(listener); + + } + + public IMapping getMapping() { + return mapping; + } + + } diff --git a/org.simantics.g3d/build.properties b/org.simantics.g3d/build.properties index 3d85ef02..a3ddc065 100644 --- a/org.simantics.g3d/build.properties +++ b/org.simantics.g3d/build.properties @@ -1,17 +1,18 @@ -############################################################################### -# Copyright (c) 2012, 2013 Association for Decentralized Information Management in -# Industry THTH ry. -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://www.eclipse.org/legal/epl-v10.html -# -# Contributors: -# VTT Technical Research Centre of Finland - initial API and implementation -############################################################################### -source.. = src/ -output.. = bin/ -bin.includes = META-INF/,\ - .,\ - plugin.xml,\ - adapters.xml +############################################################################### +# Copyright (c) 2012, 2013 Association for Decentralized Information Management in +# Industry THTH ry. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# VTT Technical Research Centre of Finland - initial API and implementation +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + adapters.xml,\ + scl/ diff --git a/org.simantics.plant3d/build.properties b/org.simantics.plant3d/build.properties index c6d4e0ab..99c99a50 100644 --- a/org.simantics.plant3d/build.properties +++ b/org.simantics.plant3d/build.properties @@ -4,4 +4,5 @@ bin.includes = META-INF/,\ .,\ plugin.xml,\ adapters.xml,\ - icons/ + icons/,\ + scl/