X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.ui%2Fsrc%2Forg%2Fsimantics%2Fui%2Fworkbench%2FResourceEditorPart.java;h=ca06a5d7b5d538c9091fb8b71d7f45d26ad906d3;hp=56c26e8b26b49e3fe333382b6722809ca42bc432;hb=20c2fa2629081d808fe313e387951f69111236b6;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.ui/src/org/simantics/ui/workbench/ResourceEditorPart.java b/bundles/org.simantics.ui/src/org/simantics/ui/workbench/ResourceEditorPart.java index 56c26e8b2..ca06a5d7b 100644 --- a/bundles/org.simantics.ui/src/org/simantics/ui/workbench/ResourceEditorPart.java +++ b/bundles/org.simantics.ui/src/org/simantics/ui/workbench/ResourceEditorPart.java @@ -1,216 +1,258 @@ -/******************************************************************************* - * Copyright (c) 2007, 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 - * Semantum Oy - issue #4384 - *******************************************************************************/ -package org.simantics.ui.workbench; - -import java.util.function.Supplier; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.jface.action.IStatusLineManager; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.IEditorInput; -import org.eclipse.ui.IEditorSite; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.part.EditorPart; -import org.simantics.db.Resource; -import org.simantics.db.Session; -import org.simantics.db.common.request.ParametrizedRead; -import org.simantics.db.event.ChangeListener; -import org.simantics.db.management.ISessionContext; -import org.simantics.ui.SimanticsUI; - -/** - * ResourceEditorPart is a base implementation for editors that support - * {@link ResourceEditorInput} style inputs for working on top of the Simantics - * graph database. - * - *

- * If you want your ResourceEditorPart implementation to receive notifications - * for all graph change events through the {@link ChangeListener} interface, - * just implement it and it will be automatically invoked by this base - * implementation. - *

- * - * @author Tuukka Lehtonen - */ -public abstract class ResourceEditorPart extends EditorPart implements IResourceEditorPart { - - protected boolean disposed = false; - protected ResourceEditorSupport support; - - /** - * Override to define your own input resource editor input validator that - * the view uses by default in {@link #init(IEditorSite, IEditorInput)}. - * - * @return - */ - protected ParametrizedRead getInputValidator() { - return null; - } - - @Override - public void init(IEditorSite site, IEditorInput input) throws PartInitException { - init(site, input, getInputValidator()); - } - - protected void createSupport(ParametrizedRead inputValidator) throws PartInitException { - support = new ResourceEditorSupport(this, inputValidator); - } - - protected void init(IEditorSite site, IEditorInput input, - ParametrizedRead inputValidator) throws PartInitException { - if (!(input instanceof IResourceEditorInput)) - throw new PartInitException("Invalid input: must be IResourceEditorInput"); - - setSite(site); - setInput(input); - createSupport(inputValidator); - - // Set initial part name according to the name given by IEditorInput - setPartName(getEditorInput().getName()); - - Session session = SimanticsUI.peekSession(); - if (session != null) { - Supplier disposedCallback = () -> disposed; - session.asyncRequest( - new TitleRequest(site.getId(), getResourceInput()), - new TitleUpdater(site.getShell().getDisplay(), this::setPartName, disposedCallback)); - session.asyncRequest( - new ToolTipRequest(site.getId(), getResourceInput()), - new TitleUpdater(site.getShell().getDisplay(), this::setTitleToolTip, disposedCallback)); - } - } - - @Override - public void dispose() { - disposed = true; - support.dispose(); - super.dispose(); - } - - protected void activateValidation() { - support.activateValidation(); - } - - public ISessionContext getSessionContext() { - return support.getSessionContext(); - } - - public Session getSession() { - return support.getSession(); - } - - /** - * A resource editor does not need to perform any save operations since the - * graph model is global and different parts of it need not be saved - * separately. - * - * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor) - */ - @Override - public void doSave(IProgressMonitor monitor) { - //System.out.println("[ResourceEditorPart] doSave: " + getPartName()); - } - - @Override - public void doSaveAs() { - //System.out.println("[ResourceEditorPart] doSaveAs: " + getPartName()); - } - - /** - * A resource editor should never be dirty since its purpose is to reflect - * the current state of the graph model. - * - * @see org.eclipse.ui.part.EditorPart#isDirty() - */ - @Override - public boolean isDirty() { - //System.out.println("[ResourceEditorPart] isDirty: " + getPartName()); - return false; - } - - @Override - public boolean isSaveAsAllowed() { - // Graph edits are always immediately sent to "UndoCore" which means - // that resource graph editors do not support save-features as such. - return false; - } - - @Override - public IResourceEditorInput getResourceInput() { - return (IResourceEditorInput) getEditorInput(); - } - - //------- - // UTILS - //------- - - public IStatusLineManager getStatusLineManager() { - IActionBars bars = getEditorSite().getActionBars(); - IStatusLineManager mgr = bars.getStatusLineManager(); - return mgr; - } - - /** - * @param message null to remove message - */ - public void setStatusMessage(String message) { - getStatusLineManager().setMessage(message); - } - - /** - * @param message null to remove message - */ - public void setStatusErrorMessage(String message) { - getStatusLineManager().setErrorMessage(message); - } - - protected Resource getInputResource() { - return getResourceInput().getResource(); - } - - protected String getInputName() { - return getEditorInput().getName(); - } - - protected String getTitleText() { - return getInputName(); - } - - protected String getTitleTooltip() { - return getInputName(); - } - - protected void updateTitle() { - setPartName(getTitleText()); - setTitleToolTip(getTitleTooltip()); - } - - /** - * A utility method for easier invocation of Runnables asynchronously in the - * SWT UI thread. - * - * @param run - */ - protected void asyncExec(Runnable run) { - getSite().getShell().getDisplay().asyncExec(run); - } - - @SuppressWarnings("unchecked") - @Override - public T getAdapter(Class adapter) { - if (adapter == Session.class) - return (T) getSession(); - return super.getAdapter(adapter); - } - -} +/******************************************************************************* + * Copyright (c) 2007, 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 + * Semantum Oy - issue #4384 + * Semantum Oy - issue #7737 + *******************************************************************************/ +package org.simantics.ui.workbench; + +import java.util.function.Supplier; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.IWorkbenchPartSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.internal.PartSite; +import org.eclipse.ui.internal.e4.compatibility.CompatibilityEditor; +import org.eclipse.ui.part.EditorPart; +import org.simantics.Simantics; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.common.request.ParametrizedRead; +import org.simantics.db.management.ISessionContext; + +/** + * ResourceEditorPart is a base implementation for editors that support + * {@link ResourceEditorInput} style inputs for working on top of the Simantics + * graph database. + * + *

+ * If you want your ResourceEditorPart implementation to receive notifications + * for all graph change events through the {@link ChangeListener} interface, + * just implement it and it will be automatically invoked by this base + * implementation. + *

+ * + * @author Tuukka Lehtonen + * @author Jani Simomaa + */ +public abstract class ResourceEditorPart extends EditorPart implements IResourceEditorPart { + + protected boolean disposed = false; + protected ResourceEditorSupport support; + + /** + * Override to define your own input resource editor input validator that + * the view uses by default in {@link #init(IEditorSite, IEditorInput)}. + * + * @return + */ + protected ParametrizedRead getInputValidator() { + return null; + } + + @Override + public void init(IEditorSite site, IEditorInput input) throws PartInitException { + init(site, input, getInputValidator()); + } + + protected void createSupport(ParametrizedRead inputValidator) throws PartInitException { + support = new ResourceEditorSupport(this, inputValidator); + } + + protected void init(IEditorSite site, IEditorInput input, + ParametrizedRead inputValidator) throws PartInitException { + if (!(input instanceof IResourceEditorInput)) + throw new PartInitException("Invalid input: must be IResourceEditorInput"); + + setSite(site); + setInput(input); + createSupport(inputValidator); + + // Set initial part name according to the name given by IEditorInput + setPartName(getEditorInput().getName()); + + Session session = Simantics.peekSession(); + if (session != null) { + Supplier disposedCallback = () -> disposed; + session.asyncRequest( + new TitleRequest(site.getId(), getResourceInput()), + new TitleUpdater(site.getShell().getDisplay(), this::safeSetPartName, disposedCallback)); + session.asyncRequest( + new ToolTipRequest(site.getId(), getResourceInput()), + new TitleUpdater(site.getShell().getDisplay(), this::safeSetTitleToolTip, disposedCallback)); + } + } + + /** + * Safely sets part name for parts whose IEditorInput is not yet disposed (e.g. + * removed from database) + * + * @param partName + */ + protected void safeSetPartName(String partName) { + if (!disposed && checkCompatibilityPartNotBeingDisposed()) { // this is to fix bug https://gitlab.simantics.org/simantics/platform/issues/117 + setPartName(partName); + } + } + + @SuppressWarnings("restriction") + private boolean checkCompatibilityPartNotBeingDisposed() { + IWorkbenchPartSite site = getSite(); + if (site instanceof PartSite) { + PartSite partSite = (PartSite) getSite(); + Object object = partSite.getModel().getObject(); + if (object instanceof CompatibilityEditor) { + CompatibilityEditor editor = (CompatibilityEditor) object; + return !editor.isBeingDisposed(); + } + } + return true; + } + + /** + * Safely sets title tooltip for parts whose IEditorInput is not yet disposed (e.g. + * removed from database) + * + * @param toolTip + */ + protected void safeSetTitleToolTip(String toolTip) { + if (!disposed) { + setTitleToolTip(toolTip); + } + } + + @Override + public void dispose() { + disposed = true; + support.dispose(); + super.dispose(); + } + + protected void activateValidation() { + support.activateValidation(); + } + + public ISessionContext getSessionContext() { + return support.getSessionContext(); + } + + public Session getSession() { + return support.getSession(); + } + + /** + * A resource editor does not need to perform any save operations since the + * graph model is global and different parts of it need not be saved + * separately. + * + * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor) + */ + @Override + public void doSave(IProgressMonitor monitor) { + //System.out.println("[ResourceEditorPart] doSave: " + getPartName()); + } + + @Override + public void doSaveAs() { + //System.out.println("[ResourceEditorPart] doSaveAs: " + getPartName()); + } + + /** + * A resource editor should never be dirty since its purpose is to reflect + * the current state of the graph model. + * + * @see org.eclipse.ui.part.EditorPart#isDirty() + */ + @Override + public boolean isDirty() { + //System.out.println("[ResourceEditorPart] isDirty: " + getPartName()); + return false; + } + + @Override + public boolean isSaveAsAllowed() { + // Graph edits are always immediately sent to "UndoCore" which means + // that resource graph editors do not support save-features as such. + return false; + } + + @Override + public IResourceEditorInput getResourceInput() { + return (IResourceEditorInput) getEditorInput(); + } + + //------- + // UTILS + //------- + + public IStatusLineManager getStatusLineManager() { + IActionBars bars = getEditorSite().getActionBars(); + IStatusLineManager mgr = bars.getStatusLineManager(); + return mgr; + } + + /** + * @param message null to remove message + */ + public void setStatusMessage(String message) { + getStatusLineManager().setMessage(message); + } + + /** + * @param message null to remove message + */ + public void setStatusErrorMessage(String message) { + getStatusLineManager().setErrorMessage(message); + } + + protected Resource getInputResource() { + return getResourceInput().getResource(); + } + + protected String getInputName() { + return getEditorInput().getName(); + } + + protected String getTitleText() { + return getInputName(); + } + + protected String getTitleTooltip() { + return getInputName(); + } + + protected void updateTitle() { + setPartName(getTitleText()); + setTitleToolTip(getTitleTooltip()); + } + + /** + * A utility method for easier invocation of Runnables asynchronously in the + * SWT UI thread. + * + * @param run + */ + protected void asyncExec(Runnable run) { + getSite().getShell().getDisplay().asyncExec(run); + } + + @SuppressWarnings("unchecked") + @Override + public T getAdapter(Class adapter) { + if (adapter == Session.class) + return (T) getSession(); + return super.getAdapter(adapter); + } + +}