From 33da5f1665afaa40754f7045347dac3ada4ffc84 Mon Sep 17 00:00:00 2001 From: lempinen Date: Tue, 12 Jul 2011 10:57:40 +0000 Subject: [PATCH] fixed the automatic editor closing when browsing deep hierarchical model structures git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/branches/simantics-1.4@21473 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../actions/ShowInstantiatedModuleAction.java | 3 +- .../sysdyn/ui/editor/DiagramViewer.java | 25 +- .../sysdyn/ui/editor/SysdynEditorInput.java | 416 ++++++++++++++++++ .../sysdyn/ui/handlers/ShowModuleHandler.java | 51 +-- 4 files changed, 439 insertions(+), 56 deletions(-) create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynEditorInput.java diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ShowInstantiatedModuleAction.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ShowInstantiatedModuleAction.java index 83c993de..9816a242 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ShowInstantiatedModuleAction.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/actions/ShowInstantiatedModuleAction.java @@ -26,6 +26,7 @@ import org.simantics.structural.stubs.StructuralResource2; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.ui.browser.BrowserSelection; import org.simantics.sysdyn.ui.browser.nodes.ModuleNode; +import org.simantics.sysdyn.ui.editor.SysdynEditorInput; import org.simantics.ui.DoubleClickEvent; import org.simantics.ui.IDoubleClickAction; import org.simantics.ui.workbench.ResourceEditorInput2; @@ -103,7 +104,7 @@ public class ShowInstantiatedModuleAction implements IDoubleClickAction { } Resource diagram = g.getSingleObject(configuration, ModelingResources.getInstance(g).CompositeToDiagram); - return new ResourceEditorInput2(EDITOR_ID, diagram, modelURI, rvi == null ? "" : "/" + rvi); + return new SysdynEditorInput(EDITOR_ID, diagram, modelURI, rvi == null ? "" : "/" + rvi); } private void addShowModuleAction(DoubleClickEvent e, final ResourceEditorInput2 editorInput) { diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java index b0b181cf..8e412512 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/DiagramViewer.java @@ -65,6 +65,8 @@ import org.simantics.sysdyn.ui.elements2.connections.SysdynConnectionClass; import org.simantics.sysdyn.ui.properties.SysdynPropertyPage; import org.simantics.utils.datastructures.hints.HintContext; import org.simantics.utils.datastructures.hints.IHintContext; +import org.simantics.utils.threads.AWTThread; +import org.simantics.utils.threads.ThreadUtils; /** * @author Tuukka Lehtonen @@ -79,13 +81,24 @@ public class DiagramViewer extends org.simantics.modeling.ui.diagramEditor.Diagr public void createPartControl(Composite parent) { super.createPartControl(parent); - ElementPainter ep = canvasContext.getSingleItem(ElementPainter.class); - for(IElement e : sourceDiagram.getElements()) { - if(e.getElementClass().getId().contains("Connection")){ - ep.update(e); + + ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() { + + @Override + public void run() { + if (isDisposed()) { + return; + } else { + ElementPainter ep = canvasContext.getSingleItem(ElementPainter.class); + for(IElement e : sourceDiagram.getElements()) { + if(e.getElementClass().getId().contains("Connection")){ + ep.update(e); + } + } + scheduleZoomToFit(); + } } - } - scheduleZoomToFit(); + }); } @Override diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynEditorInput.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynEditorInput.java new file mode 100644 index 00000000..7789c2af --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/SysdynEditorInput.java @@ -0,0 +1,416 @@ +package org.simantics.sysdyn.ui.editor; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IPersistableElement; +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.common.ResourceArray; +import org.simantics.db.common.request.ReadRequest; +import org.simantics.db.exception.AdaptionException; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.ResourceNotFoundException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.db.service.LifecycleSupport; +import org.simantics.db.service.SerialisationSupport; +import org.simantics.layer0.Layer0; +import org.simantics.ui.SimanticsUI; +import org.simantics.ui.icons.ImageDescriptorProvider; +import org.simantics.ui.workbench.ResourceEditorInput2; +import org.simantics.ui.workbench.ResourceEditorInputFactory2; +import org.simantics.ui.workbench.TitleRequest; +import org.simantics.ui.workbench.ToolTipRequest; +import org.simantics.utils.ObjectUtils; +import org.simantics.utils.datastructures.cache.ProvisionException; +import org.simantics.utils.ui.ErrorLogger; +import org.simantics.utils.ui.workbench.StringMemento; + +/** + * TEMPORARY fix to support sysdyn + * + * @author tlteemu + * + */ +public class SysdynEditorInput extends ResourceEditorInput2 { + + private final static boolean DEBUG_UPDATE = false; + + private static final String NO_NAME = "(no name)"; + + private final String editorID; + + private final String modelURI; + + private final String rvi; + + private String randomAccessResourceId; + + private transient Resource resource; + + /** + * Gotten from the editor that needs to initialize this input. Currently + * needed for two things: {@link #exists()} and {@link #saveState(IMemento)}. + */ + private transient Session session; + + private transient boolean exists; + + private transient String name; + + private transient String tooltip; + + private transient ImageDescriptor imageDesc; + + /** Persistent memento for external data */ + private final StringMemento persistentStore = new StringMemento(); + + /** + * @param editorID + * @param r + */ + public SysdynEditorInput(String editorID, Resource r, String modelURI, String rvi) { + super(editorID, r, modelURI, rvi); + if (editorID == null) + throw new IllegalArgumentException("null editor id"); + if (r == null) + throw new IllegalArgumentException("null resource"); + + this.editorID = editorID; + this.randomAccessResourceId = ""; + this.resource = r; + this.modelURI = modelURI; + this.rvi = rvi; + this.session = SimanticsUI.getSession(); + + ensureRandomAccessId(); + setNonExistant(); + } + + /** + * @param editorID + * @param randomAccessResourceId + */ + public SysdynEditorInput(String editorID, String randomAccessResourceId, String modelURI, String rvi) { + super(editorID, randomAccessResourceId, modelURI, rvi); + if (editorID == null) + throw new IllegalArgumentException("null editor id"); + if (randomAccessResourceId == null) + throw new IllegalArgumentException("null resource id"); + + this.editorID = editorID; + this.randomAccessResourceId = randomAccessResourceId; + this.resource = null; + this.modelURI = modelURI; + this.rvi = rvi; + this.session = SimanticsUI.getSession(); + + setNonExistant(); + } + + void ensureRandomAccessId() { + if (resource == null) + throw new IllegalStateException("resource is null, input is disposed"); + // Make sure that the resource has a random access id + try { + SerialisationSupport support = session.getService(SerialisationSupport.class); + randomAccessResourceId = String.valueOf(support.getRandomAccessId(resource)); + } catch (DatabaseException e) { + throw new RuntimeException(e); + } + } + + @Override + public void init(IAdaptable adapter) throws DatabaseException { + if (resource == null && randomAccessResourceId != null) { + getSession().syncRequest(new ReadRequest() { + @Override + public void run(ReadGraph g) throws DatabaseException { + try { + long id = Long.parseLong(randomAccessResourceId); + resource = g.getService(SerialisationSupport.class).getResource(id); + update(g); + } catch (NumberFormatException e) { + setNonExistant(); + } catch (DatabaseException e) { + setNonExistant(); + } + } + }); + } else { + if (resource != null) { + updateCaches(getSession(), true); + } + } + } + + @Override + public void dispose() { + //System.out.println("dispose resource editor input: " + name); + // NOTE: this has to be done since Eclipse will cache these IEditorInput + // instances within EditorHistoryItem's that are stored in an EditorHistory + // instance. They are held by strong reference which means that the session + // cannot be collected if it is not nulled here. + session = null; + resource = null; + } + + /** + * @return a graph instance if it exists and has not yet been disposed, + * null otherwise + */ + public Session getSession() { + // TODO: also throw an exception if the session is disposed + if (session == null) + throw new IllegalStateException("session is disposed"); + return session; + } + + @Override + public boolean exists() { + return exists; + } + + @Override + public boolean exists(ReadGraph graph) throws DatabaseException { + try { + assertExists(graph); + return true; + } catch (ResourceNotFoundException e) { + } catch (Nonexistant e) { + } + return false; + } + + @Override + public Resource getResource() { + return resource; + } + + @Override + @Deprecated + public ResourceArray getResourceArray() { + return new ResourceArray(resource); + } + + @Override + public String getModelURI() { + return modelURI; + } + + @Override + public String getRVI() { + return rvi; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IEditorInput#getImageDescriptor() + */ + @Override + public ImageDescriptor getImageDescriptor() { + return imageDesc; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IEditorInput#getName() + */ + @Override + public String getName() { + return name; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IEditorInput#getToolTipText() + */ + @Override + public String getToolTipText() { + return tooltip; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IEditorInput#getPersistable() + */ + @Override + public IPersistableElement getPersistable() { + // Don't allow persistability when it's not possible. + if (!isPersistable()) + return null; + return this; + } + + protected boolean isPersistable() { + if (session == null) + return false; + LifecycleSupport lc = session.peekService(LifecycleSupport.class); + if (lc == null) + return false; + if (lc.isClosed()) + return false; + return true; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IPersistableElement#getFactoryId() + */ + @Override + public String getFactoryId() { + return ResourceEditorInputFactory2.getFactoryId(); + } + + /** + * Saves the state of the given resource editor input into the given memento. + * + * @param memento the storage area for element state + * @see org.eclipse.ui.IPersistable#saveState(org.eclipse.ui.IMemento) + */ + @Override + public void saveState(IMemento memento) { +// List ids = randomAccessResourceId; + if (randomAccessResourceId == null) { + // Must create a new random access ID. + ensureRandomAccessId(); + } + IMemento child = memento.createChild(ResourceEditorInputFactory2.TAG_RESOURCE_ID); + child.putTextData(randomAccessResourceId); + memento.putString(ResourceEditorInputFactory2.TAG_EDITOR_ID, editorID); + memento.putString(ResourceEditorInputFactory2.TAG_MODEL_URI, modelURI); + memento.putString(ResourceEditorInputFactory2.TAG_RVI, rvi); + memento.putString(ResourceEditorInputFactory2.TAG_EXTERNAL_MEMENTO_ID, persistentStore.toString()); + } + + /* (non-Javadoc) + * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) + */ + @SuppressWarnings("rawtypes") + @Override + public Object getAdapter(Class adapter) { + //System.out.println("[ResourceEditorInput] getAdapter: " + adapter.getName()); + return null; + } + + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + editorID.hashCode(); + result = prime * result + ObjectUtils.hashCode(modelURI); + result = prime * result + ObjectUtils.hashCode(rvi); + result = prime * result + ObjectUtils.hashCode(randomAccessResourceId); + return result; + } + + private void updateCaches(RequestProcessor processor, boolean sync) throws DatabaseException { + ReadRequest req = new ReadRequest() { + @Override + public void run(ReadGraph g) throws DatabaseException { + update(g); + } + }; + if (sync) { + processor.syncRequest(req); + } else { + processor.asyncRequest(req); + } + } + + static class Nonexistant extends DatabaseException { + private static final long serialVersionUID = -7964385375237203651L; + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } + } + + /* (non-Javadoc) + * @see org.simantics.ui.workbench.IResourceEditorInput#update(org.simantics.db.Graph) + */ + @Override + public void update(ReadGraph g) throws DatabaseException { + Resource r = getResource(); + if (r == null) + return; + + if (DEBUG_UPDATE) + System.out.println("update(" + this + ")"); + + try { + assertExists(g); + + name = g.syncRequest(new TitleRequest(editorID, this)); + if (name == null) + name = NO_NAME; + + tooltip = g.syncRequest(new ToolTipRequest(editorID, this)); + if (tooltip == null) + tooltip = NO_NAME; + + try { + ImageDescriptorProvider idp = g.adapt(r, ImageDescriptorProvider.class); + imageDesc = idp.get(); + } catch (AdaptionException e) { + imageDesc = ImageDescriptor.getMissingImageDescriptor(); + } catch (ProvisionException e) { + imageDesc = ImageDescriptor.getMissingImageDescriptor(); + ErrorLogger.defaultLogError(e); + } + + if (DEBUG_UPDATE) + System.out.println("update(" + this + ") finished"); + } catch (DatabaseException e) { + if (DEBUG_UPDATE) + e.printStackTrace(); + setNonExistant(); + } + } + + private void assertExists(ReadGraph g) throws DatabaseException { + Resource r = getResource(); + if (r == null) + throw new Nonexistant(); + + // 1. Check resource existence + boolean exists = g.hasStatement(r); + if (!exists) + throw new Nonexistant(); + + Layer0 L0 = Layer0.getInstance(g); + // 2. Validate modelURI + if (getModelURI() != null) { + // 3. Validate RVI + Resource model = g.getResource(modelURI); + Resource baseRealization = g.getPossibleObject(model, L0.HasBaseRealization); + Variable modelVariable = Variables.getVariable(g, g.getURI(baseRealization)); + modelVariable.browse(g, getRVI()); + } + + // Touch the diagram title calculation within this existence + // checking request. + g.syncRequest(new TitleRequest(editorID, this)); + } + + private void setNonExistant() { + if (DEBUG_UPDATE) + System.out.println("setNonExistant(" + this + " @ " + System.identityHashCode(this) + ")"); + + exists = false; + tooltip = name = NO_NAME; + imageDesc = ImageDescriptor.getMissingImageDescriptor(); + } + + public IMemento getPersistentStore() { + return persistentStore; + } + + @Override + public String toString() { + return getClass().getSimpleName() + " [name=" + getName() + ", resource=" + resource + "]"; + } + + + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ShowModuleHandler.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ShowModuleHandler.java index 6c289d66..27220788 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ShowModuleHandler.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/handlers/ShowModuleHandler.java @@ -32,9 +32,9 @@ import org.simantics.modeling.ModelingResources; import org.simantics.structural.stubs.StructuralResource2; import org.simantics.sysdyn.SysdynResource; import org.simantics.sysdyn.ui.editor.DiagramViewer; +import org.simantics.sysdyn.ui.editor.SysdynEditorInput; import org.simantics.ui.SimanticsUI; import org.simantics.ui.utils.ResourceAdaptionUtils; -import org.simantics.ui.workbench.ResourceEditorInput2; import org.simantics.utils.ui.workbench.WorkbenchUtils; @@ -90,59 +90,12 @@ public class ShowModuleHandler extends AbstractHandler { public void run() { try { String editorId = EDITOR_ID; - WorkbenchUtils.openEditor(editorId, new ResourceEditorInput2(editorId, diagram, modelURI, finalRvi)); + WorkbenchUtils.openEditor(editorId, new SysdynEditorInput(editorId, diagram, modelURI, finalRvi)); } catch (PartInitException e) { e.printStackTrace(); } } }); - - /* - - - final Resource diagram = ComponentUtils.getPossibleCompositeDiagram(graph, configuration); - - if(diagram == null) return; - - String finalRvi = uri + "/" + graph.getPossibleRelatedValue(component, l0.HasName, Bindings.STRING); - - // This is ugly but it has to be done like this because WorkModel example has too PartOfs - Resource rootLibrary = graph.getPossibleObject(model, l0.PartOf); - while(!graph.getObjects(rootLibrary, l0.PartOf).isEmpty()) { - for(Resource possibleLibrary : graph.getObjects(rootLibrary, l0.PartOf)){ - if(graph.isInstanceOf(possibleLibrary, l0.Library)) { - rootLibrary = possibleLibrary; - break; - } - } - } - Variable rootVariable = graph.adapt(rootLibrary, Variable.class); - - String moduleUri = modelURI + "/BaseRealization" + finalRvi; - Variable var = rootVariable.browsePossible(graph, moduleUri.substring(6)); - if(var == null) { - finalRvi = ""; - } - final String rvi = finalRvi; - - PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { - - @Override - public void run() { - // for (Triple in : ins) { - try { - String editorId = EDITOR_ID; -// System.out.println("Activating diagram: model=" + modelURI + " rvi='" + rvi + "'"); - System.out.println("SHOW MODULE: " + modelURI + ", " + rvi); - WorkbenchUtils.openEditor(editorId, new ResourceEditorInput2(editorId, diagram, modelURI, rvi)); - } catch (PartInitException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - // } - } - }); - */ } -- 2.47.1