blob: 7b0623754152fa4734897c643fe98866a6685c12 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.ActiveShellExpression;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorLauncher;
import org.eclipse.ui.IEditorMatchingStrategy;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPathEditorInput;
import org.eclipse.ui.IPersistableElement;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.ISaveablePart;
import org.eclipse.ui.ISaveablePart2;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ListSelectionDialog;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.internal.dialogs.EventLoopProgressMonitor;
import org.eclipse.ui.internal.editorsupport.ComponentSupport;
import org.eclipse.ui.internal.misc.Assert;
import org.eclipse.ui.internal.misc.ExternalEditor;
import org.eclipse.ui.internal.misc.StatusUtil;
import org.eclipse.ui.internal.misc.UIStats;
import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
import org.eclipse.ui.internal.registry.EditorDescriptor;
import org.eclipse.ui.internal.util.Util;
import org.eclipse.ui.model.AdaptableList;
import org.eclipse.ui.model.BaseWorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchPartLabelProvider;
import org.eclipse.ui.part.MultiEditor;
import org.eclipse.ui.part.MultiEditorInput;
/**
* Manage a group of element editors. Prevent the creation of two editors on
* the same element.
*
* 06/12/00 - DS - Given the ambiguous editor input type, the manager delegates
* a number of responsabilities to the editor itself.
*
* <ol>
* <li>The editor should determine its own title.</li>
* <li>The editor shoudl listen to resource deltas and close itself if the input is deleted.
* It may also choose to stay open if the editor has dirty state.</li>
* <li>The editor should persist its own state plus editor input.</li>
* </ol>
*/
public class EditorManager implements IExtensionChangeHandler {
EditorAreaHelper editorPresentation;
WorkbenchWindow window;
WorkbenchPage page;
private Map actionCache = new HashMap();
private static final String PIN_EDITOR_KEY = "PIN_EDITOR"; //$NON-NLS-1$
private static final String PIN_EDITOR = "ovr16/pinned_ovr.gif"; //$NON-NLS-1$
// When the user removes or adds the close editors automatically preference
// the icon should be removed or added accordingly
private IPropertyChangeListener editorPropChangeListnener = null;
// Handler for the pin editor keyboard shortcut
private IHandlerActivation pinEditorHandlerActivation = null;
private static final String RESOURCES_TO_SAVE_MESSAGE = WorkbenchMessages.EditorManager_saveResourcesMessage;
private static final String SAVE_RESOURCES_TITLE = WorkbenchMessages.EditorManager_saveResourcesTitle;
/**
* EditorManager constructor comment.
*/
public EditorManager(WorkbenchWindow window, WorkbenchPage workbenchPage,
EditorAreaHelper pres) {
Assert.isNotNull(window);
Assert.isNotNull(workbenchPage);
Assert.isNotNull(pres);
this.window = window;
this.page = workbenchPage;
this.editorPresentation = pres;
page.getExtensionTracker().registerHandler(this, null);
}
/**
* Check to determine if the editor resources are no longer needed
* removes property change listener for editors
* removes pin editor keyboard shortcut handler
* disposes cached images and clears the cached images hash table
*/
void checkDeleteEditorResources() {
// get the current number of editors
IEditorReference[] editors = page.getEditorReferences();
// If there are no editors
if (editors.length == 0) {
if (editorPropChangeListnener != null) {
// remove property change listener for editors
IPreferenceStore prefStore = WorkbenchPlugin.getDefault()
.getPreferenceStore();
prefStore
.removePropertyChangeListener(editorPropChangeListnener);
editorPropChangeListnener = null;
}
if (pinEditorHandlerActivation != null) {
// remove pin editor keyboard shortcut handler
final IHandlerService handlerService = (IHandlerService) window
.getWorkbench().getAdapter(IHandlerService.class);
handlerService.deactivateHandler(pinEditorHandlerActivation);
pinEditorHandlerActivation = null;
}
}
}
/**
* Check to determine if the property change listener for editors should be created
*/
void checkCreateEditorPropListener() {
if (editorPropChangeListnener == null) {
// Add a property change listener for closing editors automatically preference
// Add or remove the pin icon accordingly
editorPropChangeListnener = new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
if (event.getProperty().equals(
IPreferenceConstants.REUSE_EDITORS_BOOLEAN)) {
IEditorReference[] editors = getEditors();
for (int i = 0; i < editors.length; i++)
((EditorReference) editors[i]).pinStatusUpdated();
}
}
};
WorkbenchPlugin.getDefault().getPreferenceStore()
.addPropertyChangeListener(editorPropChangeListnener);
}
}
/**
* Check to determine if the handler for the pin editor keyboard shortcut
* should be created.
*/
void checkCreatePinEditorShortcutKeyHandler() {
if (pinEditorHandlerActivation == null) {
final Shell shell = window.getShell();
final IHandler pinEditorHandler = new AbstractHandler() {
public final Object execute(final ExecutionEvent event) {
// check if the "Close editors automatically" preference is
// set
if (WorkbenchPlugin.getDefault().getPreferenceStore()
.getBoolean(
IPreferenceConstants.REUSE_EDITORS_BOOLEAN)) {
IWorkbenchPartReference ref = editorPresentation.getVisibleEditor();
if (ref instanceof WorkbenchPartReference) {
WorkbenchPartReference concreteRef = (WorkbenchPartReference) ref;
concreteRef.setPinned(concreteRef.isPinned());
}
}
return null;
}
};
// Assign the handler for the pin editor keyboard shortcut.
final IHandlerService handlerService = (IHandlerService) window
.getWorkbench().getAdapter(IHandlerService.class);
pinEditorHandlerActivation = handlerService.activateHandler(
"org.eclipse.ui.window.pinEditor", pinEditorHandler, //$NON-NLS-1$
new ActiveShellExpression(shell),
ActiveShellExpression.SOURCES);
}
}
/**
* Method to create the editor's pin ImageDescriptor
*
* @return the single image descriptor for the editor's pin icon
*/
ImageDescriptor getEditorPinImageDesc() {
ImageRegistry registry = JFaceResources.getImageRegistry();
ImageDescriptor pinDesc = registry.getDescriptor(PIN_EDITOR_KEY);
// Avoid registering twice
if (pinDesc == null) {
pinDesc = WorkbenchImages.getWorkbenchImageDescriptor(PIN_EDITOR);
registry.put(PIN_EDITOR_KEY, pinDesc);
}
return pinDesc;
}
/**
* Answer a list of dirty editors.
*/
private List collectDirtyEditors() {
List result = new ArrayList(3);
IEditorReference[] editors = page.getEditorReferences();
for (int i = 0; i < editors.length; i++) {
IEditorPart part = (IEditorPart) editors[i].getPart(false);
if (part != null && part.isDirty())
result.add(part);
}
return result;
}
/**
* Returns whether the manager contains an editor.
*/
public boolean containsEditor(IEditorReference ref) {
IEditorReference[] editors = page.getEditorReferences();
for (int i = 0; i < editors.length; i++) {
if (ref == editors[i])
return true;
}
return false;
}
/*
* 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 EditorActionBars createEditorActionBars(EditorDescriptor desc) {
// Get the editor type.
String type = desc.getId();
// If an action bar already exists for this editor type return it.
EditorActionBars actionBars = (EditorActionBars) actionCache.get(type);
if (actionBars != null) {
actionBars.addRef();
return actionBars;
}
// Create a new action bar set.
actionBars = new EditorActionBars(
(WWinActionBars) page.getActionBars(), type);
actionBars.addRef();
actionCache.put(type, 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;
}
/*
* Creates the action bars for an editor.
*/
private EditorActionBars createEmptyEditorActionBars() {
// Get the editor type.
String type = String.valueOf(System.currentTimeMillis());
// Create a new action bar set.
// Note: It is an empty set.
EditorActionBars actionBars = new EditorActionBars(
(WWinActionBars) page.getActionBars(), type);
actionBars.addRef();
actionCache.put(type, actionBars);
// Return action bars.
return actionBars;
}
/*
* Dispose
*/
void disposeEditorActionBars(EditorActionBars actionBars) {
actionBars.removeRef();
if (actionBars.getRef() <= 0) {
String type = actionBars.getEditorType();
actionCache.remove(type);
// refresh the cool bar manager before disposing of a cool item
if (window.getCoolBarManager() != null) {
window.getCoolBarManager().refresh();
}
actionBars.dispose();
}
}
/**
* Returns an open editor matching the given editor input.
* If none match, returns <code>null</code>.
*
* @param input the editor input
* @return the matching editor, or <code>null</code> if no match fond
*/
public IEditorPart findEditor(IEditorInput input) {
return findEditor(null, input, WorkbenchPage.MATCH_INPUT);
}
/**
* Returns an open editor matching the given editor input.
* If none match, returns <code>null</code>.
*
* @param input the editor input
* @param matchFlags flags specifying which aspects to match
* @return the matching editor, or <code>null</code> if no match fond
* @since 3.1
*/
public IEditorPart findEditor(String editorId, IEditorInput input, int matchFlags) {
if (matchFlags == WorkbenchPage.MATCH_NONE) {
return null;
}
ArrayList othersList = new ArrayList(Arrays.asList(page.getEditorReferences()));
if (othersList.isEmpty()) {
return null;
}
IEditorReference active = page.getActiveEditorReference();
if (active != null) {
othersList.remove(active);
ArrayList activeList = new ArrayList(1);
activeList.add(active);
IEditorPart match = findEditor(editorId, input, activeList, matchFlags);
if (match != null) {
return match;
}
}
return findEditor(editorId, input, othersList, matchFlags);
}
/**
* Returns an open editor matching the given editor id and/or editor input.
* Returns <code>null</code> if none match.
*
* @param editorId the editor id
* @param input the editor input
* @param editorList a mutable list containing the references for the editors to check (warning: items may be removed)
* @return the matching editor, or <code>null</code> if no match fond
* @since 3.1
*/
private IEditorPart findEditor(String editorId, IEditorInput input, ArrayList editorList, int matchFlags) {
// Phase 0: Remove editors whose ids don't match (if matching by id)
if (((matchFlags & WorkbenchPage.MATCH_ID) != 0) && editorId != null) {
for (Iterator i = editorList.iterator(); i.hasNext();) {
EditorReference editor = (EditorReference) i.next();
if (!editorId.equals(editor.getId())) {
i.remove();
}
}
}
// If not matching on editor input, just return the first match, or null if none.
// In practice, this case is never used.
if ((matchFlags & WorkbenchPage.MATCH_INPUT) == 0) {
return editorList.isEmpty() ? null : ((IEditorReference) editorList.get(0)).getEditor(true);
}
// Phase 1: check editors that have their own matching strategy
for (Iterator i = editorList.iterator(); i.hasNext();) {
EditorReference editor = (EditorReference) i.next();
IEditorDescriptor desc = editor.getDescriptor();
if (desc != null) {
IEditorMatchingStrategy matchingStrategy = desc.getEditorMatchingStrategy();
if (matchingStrategy != null) {
i.remove(); // We're handling this one here, so remove it from the list.
if (matchingStrategy.matches(editor, input)) {
return editor.getEditor(true);
}
}
}
}
// Phase 2: check materialized editors (without their own matching strategy)
for (Iterator i = editorList.iterator(); i.hasNext();) {
EditorReference editor = (EditorReference) i.next();
IEditorPart part = (IEditorPart) editor.getPart(false);
if (part != null) {
i.remove(); // We're handling this one here, so remove it from the list.
if (part.getEditorInput() != null && part.getEditorInput().equals(input)) {
return part;
}
}
}
// Phase 3: check unmaterialized editors for input equality,
// delaying plug-in activation further by only restoring the editor input
// if the editor reference's factory id and name match.
String name = input.getName();
IPersistableElement persistable = input.getPersistable();
if (name == null || persistable == null)
return null;
String id = persistable.getFactoryId();
if (id == null)
return null;
for (Iterator i = editorList.iterator(); i.hasNext();) {
EditorReference editor = (EditorReference) i.next();
if (name.equals(editor.getName()) && id.equals(editor.getFactoryId())) {
IEditorInput restoredInput;
try {
restoredInput = editor.getEditorInput();
if (Util.equals(restoredInput, input)) {
return editor.getEditor(true);
}
} catch (PartInitException e1) {
WorkbenchPlugin.log(e1);
}
}
}
return null;
}
/**
* Returns the SWT Display.
*/
private Display getDisplay() {
return window.getShell().getDisplay();
}
/**
* Answer the number of editors.
*/
public int getEditorCount() {
return page.getEditorReferences().length;
}
/*
* Answer the editor registry.
*/
private IEditorRegistry getEditorRegistry() {
return WorkbenchPlugin.getDefault().getEditorRegistry();
}
/*
* See IWorkbenchPage.
*/
public IEditorPart[] getDirtyEditors() {
List dirtyEditors = collectDirtyEditors();
return (IEditorPart[]) dirtyEditors
.toArray(new IEditorPart[dirtyEditors.size()]);
}
/*
* See IWorkbenchPage.
*/
public IEditorReference[] getEditors() {
return page.getEditorReferences();
}
/*
* See IWorkbenchPage#getFocusEditor
*/
public IEditorPart getVisibleEditor() {
IEditorReference ref = editorPresentation.getVisibleEditor();
if (ref == null)
return null;
return (IEditorPart) ref.getPart(true);
}
/**
* Answer true if save is needed in any one of the editors.
*/
public boolean isSaveAllNeeded() {
IEditorReference[] editors = page.getEditorReferences();
for (int i = 0; i < editors.length; i++) {
IEditorReference ed = editors[i];
if (ed.isDirty())
return true;
}
return false;
}
/*
* Prompt the user to save the reusable editor.
* Return false if a new editor should be opened.
*/
private IEditorReference findReusableEditor(EditorDescriptor desc) {
IEditorReference editors[] = page.getSortedEditors();
IPreferenceStore store = WorkbenchPlugin.getDefault()
.getPreferenceStore();
boolean reuse = store
.getBoolean(IPreferenceConstants.REUSE_EDITORS_BOOLEAN);
if (!reuse)
return null;
if (editors.length < page.getEditorReuseThreshold())
return null;
IEditorReference dirtyEditor = null;
//Find a editor to be reused
for (int i = 0; i < editors.length; i++) {
IEditorReference editor = editors[i];
// if(editor == activePart)
// continue;
if (editor.isPinned())
continue;
if (editor.isDirty()) {
if (dirtyEditor == null) //ensure least recently used
dirtyEditor = editor;
continue;
}
return editor;
}
if (dirtyEditor == null)
return null;
/*fix for 11122*/
boolean reuseDirty = store
.getBoolean(IPreferenceConstants.REUSE_DIRTY_EDITORS);
if (!reuseDirty)
return null;
MessageDialog dialog = new MessageDialog(
window.getShell(),
WorkbenchMessages.EditorManager_reuseEditorDialogTitle, null, // accept the default window icon
NLS.bind(WorkbenchMessages.EditorManager_saveChangesQuestion, dirtyEditor.getName()),
MessageDialog.QUESTION,
new String[] {
IDialogConstants.YES_LABEL,
IDialogConstants.NO_LABEL,
WorkbenchMessages.EditorManager_openNewEditorLabel },
0);
int result = dialog.open();
if (result == 0) { //YES
ProgressMonitorDialog pmd = new ProgressMonitorJobsDialog(dialog
.getShell());
pmd.open();
dirtyEditor.getEditor(true).doSave(pmd.getProgressMonitor());
pmd.close();
} else if ((result == 2) || (result == -1)) {
return null;
}
return dirtyEditor;
}
/*
* See IWorkbenchPage.
*/
public IEditorReference openEditor(String editorId, IEditorInput input,
boolean setVisible) throws PartInitException {
if (editorId == null || input == null) {
throw new IllegalArgumentException();
}
IEditorRegistry reg = getEditorRegistry();
EditorDescriptor desc = (EditorDescriptor) reg.findEditor(editorId);
if (desc == null) {
throw new PartInitException(
NLS.bind(WorkbenchMessages.EditorManager_unknownEditorIDMessage,editorId ));
}
IEditorReference result = openEditorFromDescriptor(desc, input);
return result;
}
/*
* Open a new editor
*/
private IEditorReference openEditorFromDescriptor(
EditorDescriptor desc, IEditorInput input) throws PartInitException {
IEditorReference result = null;
if (desc.isInternal()) {
result = reuseInternalEditor(desc, input);
if (result == null) {
result = new EditorReference(this, input, desc);
}
} else if (desc.getId()
.equals(IEditorRegistry.SYSTEM_INPLACE_EDITOR_ID)) {
if (ComponentSupport.inPlaceEditorSupported()) {
result = new EditorReference(this, input, desc);
}
} else if (desc.getId().equals(
IEditorRegistry.SYSTEM_EXTERNAL_EDITOR_ID)) {
IPathEditorInput pathInput = getPathEditorInput(input);
if (pathInput != null) {
result = openSystemExternalEditor(pathInput.getPath());
} else {
throw new PartInitException(WorkbenchMessages.EditorManager_systemEditorError);
}
} else if (desc.isOpenExternal()) {
result = openExternalEditor(desc, input);
} else {
// this should never happen
throw new PartInitException(
NLS.bind(WorkbenchMessages.EditorManager_invalidDescriptor, desc.getId() ));
}
if (result != null) {
createEditorTab((EditorReference)result, ""); //$NON-NLS-1$
}
Workbench wb = (Workbench) window.getWorkbench();
wb.getEditorHistory().add(input, desc);
return result;
}
/**
* Open a specific external editor on an file based on the descriptor.
*/
private IEditorReference openExternalEditor(final EditorDescriptor desc,
IEditorInput input) throws PartInitException {
final CoreException ex[] = new CoreException[1];
final IPathEditorInput pathInput = getPathEditorInput(input);
if (pathInput != null) {
BusyIndicator.showWhile(getDisplay(), new Runnable() {
public void run() {
try {
if (desc.getLauncher() != null) {
// open using launcher
Object launcher = WorkbenchPlugin.createExtension(
desc.getConfigurationElement(), "launcher"); //$NON-NLS-1$
((IEditorLauncher) launcher).open(pathInput
.getPath());
} else {
// open using command
ExternalEditor oEditor = new ExternalEditor(
pathInput.getPath(), desc);
oEditor.open();
}
} catch (CoreException e) {
ex[0] = e;
}
}
});
} else {
throw new PartInitException(
NLS.bind(WorkbenchMessages.EditorManager_errorOpeningExternalEditor, desc.getFileName(), desc.getId() ));
}
if (ex[0] != null) {
throw new PartInitException(
NLS.bind(WorkbenchMessages.EditorManager_errorOpeningExternalEditor, desc.getFileName(), desc.getId() ), ex[0]);
}
// we do not have an editor part for external editors
return null;
}
/**
* Create the part and reference for each inner editor.
*
* @param ref the MultiEditor ref
* @param part the part
* @param input the MultiEditor input
* @return the array of inner references to store in the MultiEditor ref
*/
IEditorReference[] openMultiEditor(final IEditorReference ref,
final MultiEditor part,
final MultiEditorInput input)
throws PartInitException {
String[] editorArray = input.getEditors();
IEditorInput[] inputArray = input.getInput();
//find all descriptors
EditorDescriptor[] descArray = new EditorDescriptor[editorArray.length];
IEditorReference refArray[] = new IEditorReference[editorArray.length];
IEditorPart partArray[] = new IEditorPart[editorArray.length];
IEditorRegistry reg = getEditorRegistry();
for (int i = 0; i < editorArray.length; i++) {
EditorDescriptor innerDesc = (EditorDescriptor) reg
.findEditor(editorArray[i]);
if (innerDesc == null)
throw new PartInitException(
NLS.bind(WorkbenchMessages.EditorManager_unknownEditorIDMessage, editorArray[i] ));
descArray[i] = innerDesc;
InnerEditor innerRef = new InnerEditor(ref, inputArray[i], descArray[i]);
refArray[i] = innerRef;
partArray[i] = innerRef.getEditor(true);
}
part.setChildren(partArray);
return refArray;
}
/*
* Opens an editor part.
*/
private void createEditorTab(final EditorReference ref, final String workbookId) throws PartInitException {
editorPresentation.addEditor(ref, workbookId);
}
/*
* Create the site and initialize it with its action bars.
*/
EditorSite createSite(final IEditorReference ref, final IEditorPart part,
final EditorDescriptor desc, final IEditorInput input)
throws PartInitException {
EditorSite site = new EditorSite(ref, part, page, desc);
if (desc != null)
site.setActionBars(createEditorActionBars(desc));
else
site.setActionBars(createEmptyEditorActionBars());
final String label = part.getTitle(); // debugging only
try {
try {
UIStats.start(UIStats.INIT_PART, label);
part.init(site, input);
} finally {
UIStats.end(UIStats.INIT_PART, part, label);
}
// Sanity-check the site
if (part.getSite() != site || part.getEditorSite() != site)
throw new PartInitException(
NLS.bind(WorkbenchMessages.EditorManager_siteIncorrect, desc.getId() ));
} catch (Exception e) {
disposeEditorActionBars((EditorActionBars) site.getActionBars());
site.dispose();
if (e instanceof PartInitException)
throw (PartInitException) e;
throw new PartInitException(WorkbenchMessages.EditorManager_errorInInit, e);
}
return site;
}
/*
* See IWorkbenchPage.
*/
private IEditorReference reuseInternalEditor(EditorDescriptor desc,
IEditorInput input) throws PartInitException {
Assert.isNotNull(desc, "descriptor must not be null"); //$NON-NLS-1$
Assert.isNotNull(input, "input must not be null"); //$NON-NLS-1$
IEditorReference reusableEditorRef = findReusableEditor(desc);
if (reusableEditorRef != null) {
IEditorPart reusableEditor = reusableEditorRef.getEditor(false);
if (reusableEditor == null) {
IEditorReference result = new EditorReference(this, input, desc);
page.closeEditor(reusableEditorRef, false);
return result;
}
EditorSite site = (EditorSite) reusableEditor.getEditorSite();
EditorDescriptor oldDesc = site.getEditorDescriptor();
if ((desc.getId().equals(oldDesc.getId()))
&& (reusableEditor instanceof IReusableEditor)) {
Workbench wb = (Workbench) window.getWorkbench();
editorPresentation.moveEditor(reusableEditor, -1);
wb.getEditorHistory().add(reusableEditor.getEditorInput(),
site.getEditorDescriptor());
page.reuseEditor((IReusableEditor) reusableEditor, input);
return reusableEditorRef;
} else {
//findReusableEditor(...) checks pinned and saves editor if necessary
IEditorReference ref = new EditorReference(this, input, desc);
reusableEditor.getEditorSite().getPage().closeEditor(
reusableEditor, false);
return ref;
}
}
return null;
}
IEditorPart createPart(final EditorDescriptor desc)
throws PartInitException {
try {
IEditorPart result = desc.createEditor();
IConfigurationElement element = desc.getConfigurationElement();
if (element != null) {
page.getExtensionTracker().registerObject(
element.getDeclaringExtension(), result,
IExtensionTracker.REF_WEAK);
}
return result;
} catch (CoreException e) {
throw new PartInitException(StatusUtil.newStatus(desc.getPluginID(), WorkbenchMessages.EditorManager_instantiationError, e));
}
}
/**
* Open a system external editor on the input path.
*/
private IEditorReference openSystemExternalEditor(final IPath location)
throws PartInitException {
if (location == null) {
throw new IllegalArgumentException();
}
final boolean result[] = { false };
BusyIndicator.showWhile(getDisplay(), new Runnable() {
public void run() {
if (location != null) {
result[0] = Program.launch(location.toOSString());
}
}
});
if (!result[0]) {
throw new PartInitException(
NLS.bind(WorkbenchMessages.EditorManager_unableToOpenExternalEditor, location ));
}
// We do not have an editor part for external editors
return null;
}
/**
* Opens a system in place editor on the input.
*/
private IEditorReference openSystemInPlaceEditor(IEditorReference ref,
EditorDescriptor desc, IEditorInput input) throws PartInitException {
IEditorPart cEditor = ComponentSupport.getSystemInPlaceEditor();
if (cEditor == null) {
return null;
} else {
return ref;
}
}
ImageDescriptor findImage(EditorDescriptor desc, IPath path) {
if (desc == null) {
// @issue what should be the default image?
return ImageDescriptor.getMissingImageDescriptor();
} else {
if (desc.isOpenExternal() && path != null) {
return PlatformUI.getWorkbench().getEditorRegistry()
.getImageDescriptor(path.toOSString());
} else {
return desc.getImageDescriptor();
}
}
}
/**
* @see IPersistablePart
*/
public IStatus restoreState(IMemento memento) {
// Restore the editor area workbooks layout/relationship
final MultiStatus result = new MultiStatus(
PlatformUI.PLUGIN_ID,
IStatus.OK,
WorkbenchMessages.EditorManager_problemsRestoringEditors, null);
final String activeWorkbookID[] = new String[1];
final ArrayList visibleEditors = new ArrayList(5);
final IEditorReference activeEditor[] = new IEditorReference[1];
final ArrayList errorWorkbooks = new ArrayList(1);
IMemento areaMem = memento.getChild(IWorkbenchConstants.TAG_AREA);
if (areaMem != null) {
result.add(editorPresentation.restoreState(areaMem));
activeWorkbookID[0] = areaMem
.getString(IWorkbenchConstants.TAG_ACTIVE_WORKBOOK);
}
// Loop through the editors.
IMemento[] editorMems = memento
.getChildren(IWorkbenchConstants.TAG_EDITOR);
for (int x = 0; x < editorMems.length; x++) {
//for dynamic UI - call restoreEditorState to replace code which is commented out
restoreEditorState(editorMems[x], visibleEditors, activeEditor, result);
}
// restore the presentation
if (areaMem != null) {
result.add(editorPresentation.restorePresentationState(areaMem));
}
Platform.run(new SafeRunnable() {
public void run() {
// Update each workbook with its visible editor.
for (int i = 0; i < visibleEditors.size(); i++)
setVisibleEditor((IEditorReference) visibleEditors.get(i),
false);
// Update the active workbook
if (activeWorkbookID[0] != null)
editorPresentation
.setActiveEditorWorkbookFromID(activeWorkbookID[0]);
if (activeEditor[0] != null) {
IWorkbenchPart editor = activeEditor[0].getPart(true);
if (editor != null) {
page.activate(editor);
}
}
}
public void handleException(Throwable e) {
//The exception is already logged.
result
.add(new Status(
IStatus.ERROR,
PlatformUI.PLUGIN_ID,
0,
WorkbenchMessages.EditorManager_exceptionRestoringEditor, e));
}
});
return result;
}
/**
* Save all of the editors in the workbench.
* Return true if successful. Return false if the
* user has cancelled the command.
*/
public boolean saveAll(boolean confirm, boolean closing) {
// Get the list of dirty editors and views. If it is
// empty just return.
ISaveablePart[] parts = page.getDirtyParts();
if (parts.length == 0)
return true;
// saveAll below expects a mutable list
List dirtyParts = new ArrayList(parts.length);
for (int i = 0; i < parts.length; i++) {
dirtyParts.add(parts[i]);
}
// If confirmation is required ..
return saveAll(dirtyParts, confirm, window);
}
/**
* Saves the given dirty editors and views, optionally prompting the user.
*
* @param dirtyParts the dirty views and editors
* @param confirm <code>true</code> prompt whether to save, <code>false</code> to save without prompting
* @param window the window to use as the parent for the dialog that prompts to save multiple dirty editors and views
* @return <code>true</code> on success, <code>false</code> if the user canceled the save
*/
public static boolean saveAll(List dirtyParts, boolean confirm,
final IWorkbenchWindow window) {
if (confirm) {
// Process all parts that implement ISaveablePart2.
// These parts are removed from the list after saving
// them. We then need to restore the workbench to
// its previous state, for now this is just last
// active perspective.
// Note that the given parts may come from multiple
// windows, pages and perspectives.
ListIterator listIterator = dirtyParts.listIterator();
WorkbenchPage currentPage = null;
Perspective currentPageOriginalPerspective = null;
while (listIterator.hasNext()) {
IWorkbenchPart part = (IWorkbenchPart) listIterator.next();
if (part instanceof ISaveablePart2) {
WorkbenchPage page = (WorkbenchPage) part.getSite().getPage();
if (!Util.equals(currentPage, page)) {
if (currentPage != null && currentPageOriginalPerspective != null) {
if (!currentPageOriginalPerspective.equals(currentPage.getActivePerspective())) {
currentPage.setPerspective(currentPageOriginalPerspective.getDesc());
}
}
currentPage = page;
currentPageOriginalPerspective = page.getActivePerspective();
}
if (confirm) {
if (part instanceof IViewPart) {
Perspective perspective = page.getFirstPerspectiveWithView((IViewPart) part);
if (perspective != null) {
page.setPerspective(perspective.getDesc());
}
}
// show the window containing the page?
IWorkbenchWindow partsWindow = page.getWorkbenchWindow();
if (partsWindow != partsWindow.getWorkbench().getActiveWorkbenchWindow()) {
Shell shell = partsWindow.getShell();
if (shell.getMinimized())
shell.setMinimized(false);
shell.setActive();
}
page.bringToTop(part);
}
// try to save the part
if (!SaveableHelper.savePart((ISaveablePart2) part, part, page.getWorkbenchWindow(), confirm)) {
// If the user cancels, don't restore the previous workbench state, as that will
// be an unexpected switch from the current state.
return false;
}
listIterator.remove();
}
}
// try to restore the workbench to its previous state
if (currentPage != null && currentPageOriginalPerspective != null) {
if (!currentPageOriginalPerspective.equals(currentPage.getActivePerspective())) {
currentPage.setPerspective(currentPageOriginalPerspective.getDesc());
}
}
// If the editor list is empty return.
if (dirtyParts.isEmpty())
return true;
// Convert the list into an element collection.
AdaptableList input = new AdaptableList(dirtyParts);
ListSelectionDialog dlg = new ListSelectionDialog(
window.getShell(), input,
new BaseWorkbenchContentProvider(),
new WorkbenchPartLabelProvider(), RESOURCES_TO_SAVE_MESSAGE);
dlg.setInitialSelections(dirtyParts
.toArray(new Object[dirtyParts.size()]));
dlg.setTitle(SAVE_RESOURCES_TITLE);
int result = dlg.open();
//Just return false to prevent the operation continuing
if (result == IDialogConstants.CANCEL_ID)
return false;
dirtyParts = Arrays.asList(dlg.getResult());
if (dirtyParts == null)
return false;
// If the editor list is empty return.
if (dirtyParts.isEmpty())
return true;
}
// Create save block.
// @issue reference to workspace runnable!
final List finalParts = dirtyParts;
/* final IWorkspaceRunnable workspaceOp = new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) {
monitor.beginTask("", finalEditors.size()); //$NON-NLS-1$
Iterator enum = finalEditors.iterator();
while (enum.hasNext()) {
IEditorPart part = (IEditorPart) enum.next();
part.doSave(new SubProgressMonitor(monitor, 1));
if (monitor.isCanceled())
break;
}
}
};
*/
IRunnableWithProgress progressOp = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) {
// try {
// @issue reference to workspace to run runnable
IProgressMonitor monitorWrap = new EventLoopProgressMonitor(
monitor);
// ResourcesPlugin.getWorkspace().run(workspaceOp, monitorWrap);
//--------- This code was in the IWorkspaceRunnable above
monitorWrap.beginTask("", finalParts.size()); //$NON-NLS-1$
Iterator itr = finalParts.iterator();
while (itr.hasNext()) {
ISaveablePart part = (ISaveablePart) itr.next();
part.doSave(new SubProgressMonitor(monitorWrap, 1));
if (monitorWrap.isCanceled())
break;
}
//-----------
monitorWrap.done();
/* } catch (CoreException e) {
IStatus status = new Status(Status.WARNING, PlatformUI.PLUGIN_ID, 0, WorkbenchMessages.getString("EditorManager.saveFailed"), e); //$NON-NLS-1$
WorkbenchPlugin.log(WorkbenchMessages.getString("EditorManager.saveFailed"), status); //$NON-NLS-1$
ErrorDialog.openError(
window.getShell(),
WorkbenchMessages.getString("Error"), //$NON-NLS-1$
WorkbenchMessages.format("EditorManager.saveFailedMessage", new Object[] { e.getMessage()}), //$NON-NLS-1$
e.getStatus());
}
*/
}
};
// Do the save.
return SaveableHelper.runProgressMonitorOperation(WorkbenchMessages.Save_All, progressOp, window);
}
/*
* Saves the workbench part.
*/
public boolean savePart(final ISaveablePart saveable, IWorkbenchPart part,
boolean confirm) {
return SaveableHelper.savePart(saveable, part, window, confirm);
}
/**
* Save and close an editor.
* Return true if successful. Return false if the
* user has cancelled the command.
*/
public boolean saveEditor(IEditorPart part, boolean confirm) {
return savePart(part, part, confirm);
}
/**
* @see IPersistablePart
*/
public IStatus saveState(final IMemento memento) {
final MultiStatus result = new MultiStatus(PlatformUI.PLUGIN_ID,
IStatus.OK, WorkbenchMessages.EditorManager_problemsSavingEditors, null);
// Save the editor area workbooks layout/relationship
IMemento editorAreaMem = memento
.createChild(IWorkbenchConstants.TAG_AREA);
result.add(editorPresentation.saveState(editorAreaMem));
// Save the active workbook id
editorAreaMem.putString(IWorkbenchConstants.TAG_ACTIVE_WORKBOOK,
editorPresentation.getActiveEditorWorkbookID());
// Get each workbook
ArrayList workbooks = editorPresentation.getWorkbooks();
for (Iterator iter = workbooks.iterator(); iter.hasNext();) {
EditorStack workbook = (EditorStack) iter.next();
// Use the list of editors found in EditorStack; fix for 24091
EditorPane editorPanes[] = workbook.getEditors();
for (int i = 0; i < editorPanes.length; i++) {
// Save each open editor.
IEditorReference editorReference = editorPanes[i]
.getEditorReference();
EditorReference e = (EditorReference) editorReference;
final IEditorPart editor = editorReference.getEditor(false);
if (editor == null) {
if (e.getMemento() != null) {
IMemento editorMem = memento
.createChild(IWorkbenchConstants.TAG_EDITOR);
editorMem.putMemento(e.getMemento());
}
continue;
}
//for dynamic UI - add the next line to replace the subsequent code which is commented out
saveEditorState(memento, e, result);
}
}
return result;
}
/**
* Shows an editor. If <code>setFocus == true</code> then
* give it focus, too.
*
* @return true if the active editor was changed, false if not.
*/
public boolean setVisibleEditor(IEditorReference newEd, boolean setFocus) {
return editorPresentation.setVisibleEditor(newEd, setFocus);
}
private IPathEditorInput getPathEditorInput(IEditorInput input) {
if (input instanceof IPathEditorInput) {
return (IPathEditorInput) input;
}
return (IPathEditorInput) input.getAdapter(IPathEditorInput.class);
}
private class InnerEditor extends EditorReference {
private IEditorReference outerEditor;
public InnerEditor(IEditorReference outerEditor, IEditorInput input, EditorDescriptor desc) {
super(EditorManager.this, input, desc);
this.outerEditor = outerEditor;
}
protected PartPane createPane() {
return new MultiEditorInnerPane((EditorPane)((EditorReference)outerEditor).getPane(),
this, page, editorPresentation.getActiveWorkbook());
}
}
protected void restoreEditorState(IMemento editorMem,
ArrayList visibleEditors, IEditorReference[] activeEditor,
MultiStatus result) {
// String strFocus = editorMem.getString(IWorkbenchConstants.TAG_FOCUS);
// boolean visibleEditor = "true".equals(strFocus); //$NON-NLS-1$
EditorReference e = new EditorReference(this, editorMem);
//if the editor is not visible, ensure it is put in the correct workbook. PR 24091
String workbookID = editorMem.getString(IWorkbenchConstants.TAG_WORKBOOK);
try {
createEditorTab(e, workbookID);
} catch (PartInitException ex) {
result.add(ex.getStatus());
}
String strActivePart = editorMem.getString(IWorkbenchConstants.TAG_ACTIVE_PART);
if ("true".equals(strActivePart)) //$NON-NLS-1$
activeEditor[0] = e;
String strFocus = editorMem.getString(IWorkbenchConstants.TAG_FOCUS);
boolean visibleEditor = "true".equals(strFocus); //$NON-NLS-1$
if (visibleEditor) {
visibleEditors.add(e);
}
}
//for dynamic UI
protected void saveEditorState(IMemento mem, IEditorReference ed,
MultiStatus res) {
final EditorReference editorRef = (EditorReference) ed;
final IEditorPart editor = ed.getEditor(false);
final IMemento memento = mem;
final MultiStatus result = res;
final EditorSite site = (EditorSite) editor.getEditorSite();
if (site.getPane() instanceof MultiEditorInnerPane)
return;
Platform.run(new SafeRunnable() {
public void run() {
// Get the input.
IEditorInput input = editor.getEditorInput();
IPersistableElement persistable = input.getPersistable();
if (persistable == null)
return;
// Save editor.
IMemento editorMem = memento
.createChild(IWorkbenchConstants.TAG_EDITOR);
editorMem.putString(IWorkbenchConstants.TAG_TITLE, editorRef
.getTitle());
editorMem.putString(IWorkbenchConstants.TAG_NAME, editorRef
.getName());
editorMem.putString(IWorkbenchConstants.TAG_ID, editorRef
.getId());
editorMem.putString(IWorkbenchConstants.TAG_TOOLTIP, editorRef
.getTitleToolTip());
editorMem.putString(IWorkbenchConstants.TAG_PART_NAME,
editorRef.getPartName());
if (editorRef.isPinned())
editorMem.putString(IWorkbenchConstants.TAG_PINNED, "true"); //$NON-NLS-1$
EditorPane editorPane = (EditorPane) ((EditorSite) editor
.getEditorSite()).getPane();
editorMem.putString(IWorkbenchConstants.TAG_WORKBOOK,
editorPane.getWorkbook().getID());
if (editor == page.getActivePart())
editorMem.putString(IWorkbenchConstants.TAG_ACTIVE_PART,
"true"); //$NON-NLS-1$
if (editorPane == editorPane.getWorkbook().getSelection())
editorMem.putString(IWorkbenchConstants.TAG_FOCUS, "true"); //$NON-NLS-1$
// TODO - DDW - dynamic UI - a check for a null input was deliberately removed here.
if (input instanceof IPathEditorInput) {
editorMem.putString(IWorkbenchConstants.TAG_PATH,
((IPathEditorInput) input).getPath().toString());
}
// Save input.
IMemento inputMem = editorMem
.createChild(IWorkbenchConstants.TAG_INPUT);
inputMem.putString(IWorkbenchConstants.TAG_FACTORY_ID,
persistable.getFactoryId());
persistable.saveState(inputMem);
}
public void handleException(Throwable e) {
result
.add(new Status(
IStatus.ERROR,
PlatformUI.PLUGIN_ID,
0,
NLS.bind(WorkbenchMessages.EditorManager_unableToSaveEditor, editorRef.getTitle() ), e));
}
});
}
//for dynamic UI
public IMemento getMemento(IEditorReference e) {
if (e instanceof EditorReference)
return ((EditorReference) e).getMemento();
return null;
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#removeExtension(org.eclipse.core.runtime.IExtension, java.lang.Object[])
*/
public void removeExtension(IExtension source, Object[] objects) {
for (int i = 0; i < objects.length; i++) {
if (objects[i] instanceof IEditorPart) {
// close the editor and clean up the editor history
IEditorPart editor = (IEditorPart) objects[i];
IEditorInput input = editor.getEditorInput();
page.closeEditor(editor, true);
((Workbench) window.getWorkbench()).getEditorHistory().remove(input);
}
}
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.dynamicHelpers.IExtensionChangeHandler#addExtension(org.eclipse.core.runtime.dynamicHelpers.IExtensionTracker, org.eclipse.core.runtime.IExtension)
*/
public void addExtension(IExtensionTracker tracker,IExtension extension) {
//Nothing to do
}
}