/*******************************************************************************
* 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);
}
}