blob: 2b7bb5a7f8a115c7220d0caa14b66078e6d0cb13 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2015 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Nikolay Botev - bug 240651
* Andrey Loskutov <loskutov@gmx.de> - Bug 459964
* Lars Vogel <Lars.Vogel@vogella.com> - Bug 472654
*******************************************************************************/
package org.eclipse.ui.internal;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.workbench.IPresentationEngine;
import org.eclipse.jface.internal.provisional.action.ICoolBarManager2;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IElementFactory;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPersistableEditor;
import org.eclipse.ui.IPersistableElement;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPart3;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;
import org.eclipse.ui.internal.editorsupport.ComponentSupport;
import org.eclipse.ui.internal.part.NullEditorInput;
import org.eclipse.ui.internal.registry.EditorDescriptor;
import org.eclipse.ui.internal.registry.EditorRegistry;
import org.eclipse.ui.internal.util.Util;
public class EditorReference extends WorkbenchPartReference implements IEditorReference {
private IEditorInput input;
private EditorDescriptor descriptor;
private final String descriptorId;
private final IMemento editorState;
private final String factoryId;
public EditorReference(IEclipseContext windowContext, IWorkbenchPage page, MPart part, IEditorInput input,
EditorDescriptor descriptor, IMemento editorState) {
super(windowContext, page, part);
this.input = input;
this.descriptor = descriptor;
this.editorState = editorState;
String factory = null;
if (descriptor == null) {
String memento = getModel().getPersistedState().get(MEMENTO_KEY);
if (memento == null) {
descriptorId = EditorRegistry.EMPTY_EDITOR_ID;
} else {
XMLMemento createReadRoot;
try {
createReadRoot = XMLMemento.createReadRoot(new StringReader(memento));
} catch (WorkbenchException e) {
WorkbenchPlugin.log(e);
descriptorId = EditorRegistry.EMPTY_EDITOR_ID;
factoryId = null;
return;
}
IEditorRegistry registry = getPage().getWorkbenchWindow().getWorkbench().getEditorRegistry();
descriptorId = createReadRoot.getString(IWorkbenchConstants.TAG_ID);
this.descriptor = (EditorDescriptor) registry.findEditor(descriptorId);
boolean pinnedVal = "true".equals(createReadRoot.getString(IWorkbenchConstants.TAG_PINNED)); //$NON-NLS-1$
setPinned(pinnedVal);
String ttip = createReadRoot.getString(IWorkbenchConstants.TAG_TOOLTIP);
part.getTransientData().put(IPresentationEngine.OVERRIDE_TITLE_TOOL_TIP_KEY, ttip);
IMemento inputMem = createReadRoot.getChild(IWorkbenchConstants.TAG_INPUT);
if (inputMem != null) {
factory = inputMem.getString(IWorkbenchConstants.TAG_FACTORY_ID);
}
}
} else {
descriptorId = this.descriptor.getId();
}
factoryId = factory;
}
boolean persist() {
XMLMemento persistedState = (XMLMemento) getEditorState();
if (persistedState == null)
return false;
StringWriter writer = new StringWriter();
try {
persistedState.save(writer);
getModel().getPersistedState().put(MEMENTO_KEY, writer.toString());
} catch (IOException e) {
WorkbenchPlugin.log(e);
return false;
}
return true;
}
IMemento getEditorState() {
IEditorPart editor = getEditor(false);
// If the editor hasn't been rendered yet then see if we can grab the
// info from the model
if (editor == null && getModel() != null) {
String savedState = getModel().getPersistedState().get(MEMENTO_KEY);
if (savedState != null) {
StringReader sr = new StringReader(savedState);
try {
return XMLMemento.createReadRoot(sr);
} catch (WorkbenchException e) {
WorkbenchPlugin.log(e);
return null;
}
}
return null;
}
IEditorInput input = editor.getEditorInput();
if (input == null) {
return null;
}
IPersistableElement persistable = input.getPersistable();
if (persistable == null) {
return null;
}
XMLMemento editorMem = XMLMemento.createWriteRoot(IWorkbenchConstants.TAG_EDITOR);
editorMem.putString(IWorkbenchConstants.TAG_ID, descriptor.getId());
editorMem.putString(IWorkbenchConstants.TAG_TITLE, getTitle());
editorMem.putString(IWorkbenchConstants.TAG_NAME, getName());
editorMem.putString(IWorkbenchConstants.TAG_ID, getId());
editorMem.putString(IWorkbenchConstants.TAG_TOOLTIP, getTitleToolTip());
editorMem.putString(IWorkbenchConstants.TAG_PART_NAME, getPartName());
if (editor instanceof IWorkbenchPart3) {
Map<String, String> properties = ((IWorkbenchPart3) editor).getPartProperties();
if (!properties.isEmpty()) {
IMemento propBag = editorMem.createChild(IWorkbenchConstants.TAG_PROPERTIES);
for (Map.Entry<String, String> entry : properties.entrySet()) {
IMemento p = propBag.createChild(IWorkbenchConstants.TAG_PROPERTY, entry.getKey());
p.putTextData(entry.getValue());
}
}
}
if (isPinned()) {
editorMem.putString(IWorkbenchConstants.TAG_PINNED, "true"); //$NON-NLS-1$
}
IMemento inputMem = editorMem.createChild(IWorkbenchConstants.TAG_INPUT);
inputMem.putString(IWorkbenchConstants.TAG_FACTORY_ID, persistable.getFactoryId());
persistable.saveState(inputMem);
if (editor instanceof IPersistableEditor) {
IMemento editorStateMem = editorMem.createChild(IWorkbenchConstants.TAG_EDITOR_STATE);
((IPersistableEditor) editor).saveState(editorStateMem);
}
return editorMem;
}
public EditorDescriptor getDescriptor() {
return descriptor;
}
@Override
public String getId() {
// by default we delegate to the model part, which is not correct for
// editors
return descriptorId;
}
@Override
public String getFactoryId() {
IEditorPart editor = getEditor(false);
if (editor == null) {
if (input == null) {
return factoryId;
}
IPersistableElement persistable = input.getPersistable();
return persistable == null ? null : persistable.getFactoryId();
}
IPersistableElement persistable = editor.getEditorInput().getPersistable();
return persistable == null ? null : persistable.getFactoryId();
}
@Override
public String getName() {
IEditorPart editor = getEditor(false);
if (input == null) {
return editor == null ? getModel().getLocalizedLabel() : editor.getEditorInput().getName();
}
return editor == null ? input.getName() : editor.getEditorInput().getName();
}
@Override
public String getTitle() {
String label = Util.safeString(getModel().getLocalizedLabel());
if (label.isEmpty()) {
if (input == null) {
if (descriptor != null) {
return descriptor.getLabel();
}
} else {
return Util.safeString(input.getName());
}
}
return label;
}
private IEditorInput restoreInput(IMemento editorMem) throws PartInitException {
return createInput(editorMem);
}
public static IEditorInput createInput(IMemento editorMem) throws PartInitException {
String editorId = editorMem.getString(IWorkbenchConstants.TAG_ID);
IMemento inputMem = editorMem.getChild(IWorkbenchConstants.TAG_INPUT);
String editorName = null;
String factoryID = null;
if (inputMem != null) {
editorName = inputMem.getString(IWorkbenchConstants.TAG_PATH);
factoryID = inputMem.getString(IWorkbenchConstants.TAG_FACTORY_ID);
}
if (factoryID == null) {
throw new PartInitException(
NLS.bind(WorkbenchMessages.EditorManager_no_input_factory_ID, editorId, editorName));
}
IAdaptable input = null;
IElementFactory factory = PlatformUI.getWorkbench().getElementFactory(factoryID);
if (factory == null) {
throw new PartInitException(NLS.bind(WorkbenchMessages.EditorManager_bad_element_factory,
new Object[] { factoryID, editorId, editorName }));
}
// Get the input element.
input = factory.createElement(inputMem);
if (input == null) {
throw new PartInitException(NLS.bind(WorkbenchMessages.EditorManager_create_element_returned_null,
new Object[] { factoryID, editorId, editorName }));
}
if (!(input instanceof IEditorInput)) {
throw new PartInitException(NLS.bind(WorkbenchMessages.EditorManager_wrong_createElement_result,
new Object[] { factoryID, editorId, editorName }));
}
return (IEditorInput) input;
}
@Override
public IEditorPart getEditor(boolean restore) {
return (IEditorPart) getPart(restore);
}
@Override
public IEditorInput getEditorInput() throws PartInitException {
IEditorPart editor = getEditor(false);
if (editor != null) {
return editor.getEditorInput();
}
if (input == null) {
String memento = getModel().getPersistedState().get(MEMENTO_KEY);
if (memento == null) {
input = new NullEditorInput();
} else {
try {
XMLMemento createReadRoot = XMLMemento.createReadRoot(new StringReader(memento));
input = restoreInput(createReadRoot);
} catch (WorkbenchException e) {
throw new PartInitException(e.getStatus());
}
}
}
return input;
}
@Override
public IWorkbenchPart createPart() throws PartInitException {
try {
if (descriptor == null) {
return createErrorPart();
} else if (descriptor.getId().equals(IEditorRegistry.SYSTEM_INPLACE_EDITOR_ID)) {
IEditorPart part = ComponentSupport.getSystemInPlaceEditor();
if (part == null) {
throw new PartInitException(WorkbenchMessages.EditorManager_no_in_place_support);
}
return part;
}
return descriptor.createEditor();
} catch (CoreException e) {
IStatus status = e.getStatus();
throw new PartInitException(
new Status(IStatus.ERROR, WorkbenchPlugin.PI_WORKBENCH, status.getCode(), status.getMessage(), e));
}
}
@Override
IWorkbenchPart createErrorPart() {
IStatus status = new Status(IStatus.ERROR, WorkbenchPlugin.PI_WORKBENCH,
NLS.bind(WorkbenchMessages.EditorManager_missing_editor_descriptor, descriptorId), new Exception());
IEditorRegistry registry = getPage().getWorkbenchWindow().getWorkbench().getEditorRegistry();
descriptor = (EditorDescriptor) registry.findEditor(EditorRegistry.EMPTY_EDITOR_ID);
return createErrorPart(status);
}
@Override
public IWorkbenchPart createErrorPart(IStatus status) {
return new ErrorEditorPart(status);
}
@Override
public void initialize(IWorkbenchPart part) throws PartInitException {
IConfigurationElement element = descriptor.getConfigurationElement();
EditorSite editorSite = new EditorSite(getModel(), part, this, element);
if (element == null) {
editorSite.setExtensionId(descriptor.getId());
}
editorSite.setActionBars(createEditorActionBars((WorkbenchPage) getPage(), descriptor));
IEditorPart editor = (IEditorPart) part;
try {
editor.init(editorSite, getEditorInput());
} catch (PartInitException e) {
if (editor instanceof ErrorEditorPart) {
editor.init(editorSite, new NullEditorInput(this));
} else {
throw e;
}
}
if (editor.getSite() != editorSite || editor.getEditorSite() != editorSite) {
String id = descriptor == null ? getModel().getElementId() : descriptor.getId();
throw new PartInitException(NLS.bind(WorkbenchMessages.EditorManager_siteIncorrect, id));
}
if (part instanceof IPersistableEditor) {
if (editorState != null) {
((IPersistableEditor) part).restoreState(editorState);
} else if (useIPersistableEditor()) {
String mementoString = getModel().getPersistedState().get(MEMENTO_KEY);
if (mementoString != null) {
try {
IMemento createReadRoot = XMLMemento.createReadRoot(new StringReader(mementoString));
IMemento editorStateMemento = createReadRoot.getChild(IWorkbenchConstants.TAG_EDITOR_STATE);
if (editorStateMemento != null) {
((IPersistableEditor) part).restoreState(editorStateMemento);
}
} catch (WorkbenchException e) {
throw new PartInitException(e.getStatus());
}
}
}
}
legacyPart = part;
addPropertyListeners();
}
@Override
public PartSite getSite() {
if (legacyPart != null) {
return (PartSite) legacyPart.getSite();
}
return null;
}
private static HashMap<String, Set<EditorActionBars>> actionCache = new HashMap<>();
/*
* Creates the action bars for an editor. Editors of the same type should share
* a single editor action bar, so this implementation may return an existing
* action bar vector.
*/
private static EditorActionBars createEditorActionBars(WorkbenchPage page, EditorDescriptor desc) {
// Get the editor type.
String type = desc.getId();
// If an action bar already exists for this editor type return it.
Set<EditorActionBars> candidates = actionCache.get(type);
if (candidates != null) {
for (EditorActionBars candidate : candidates) {
if (candidate.getPage() == page) {
candidate.addRef();
return candidate;
}
}
}
// Create a new action bar set.
EditorActionBars actionBars = new EditorActionBars(page, page.getWorkbenchWindow(), type);
actionBars.addRef();
if (candidates == null) {
candidates = new HashSet<>(3);
candidates.add(actionBars);
actionCache.put(type, candidates);
} else
candidates.add(actionBars);
// Read base contributor.
IEditorActionBarContributor contr = desc.createActionBarContributor();
if (contr != null) {
actionBars.setEditorContributor(contr);
contr.init(actionBars, page);
}
// Read action extensions.
EditorActionBuilder builder = new EditorActionBuilder();
contr = builder.readActionExtensions(desc);
if (contr != null) {
actionBars.setExtensionContributor(contr);
contr.init(actionBars, page);
}
// Return action bars.
return actionBars;
}
public static void disposeEditorActionBars(EditorActionBars actionBars) {
actionBars.removeRef();
if (actionBars.getRef() <= 0) {
String type = actionBars.getEditorType();
Set<EditorActionBars> set = actionCache.get(type);
if (set != null) {
set.remove(actionBars);
}
// refresh the cool bar manager before disposing of a cool item
ICoolBarManager2 coolBar = (ICoolBarManager2) ((WorkbenchWindow) actionBars.getPage().getWorkbenchWindow())
.getCoolBarManager2();
if (coolBar != null) {
coolBar.refresh();
}
actionBars.dispose();
}
}
private static boolean useIPersistableEditor() {
IPreferenceStore store = WorkbenchPlugin.getDefault().getPreferenceStore();
return store.getBoolean(IPreferenceConstants.USE_IPERSISTABLE_EDITORS);
}
}