package org.eclipse.ui.internal;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.ui.internal.model.AdaptableList;
import org.eclipse.ui.internal.registry.*;
import org.eclipse.ui.*;
import org.eclipse.ui.*;
import org.eclipse.ui.*;
import org.eclipse.ui.internal.dialogs.*;
import org.eclipse.ui.internal.misc.*;
import org.eclipse.ui.dialogs.*;
import org.eclipse.ui.part.*;
import org.eclipse.ui.model.*;
import org.eclipse.swt.program.Program;
import org.eclipse.ui.internal.editorsupport.ComponentSupport;
import org.eclipse.jface.dialogs.*;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.operation.*;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Display;
import java.lang.reflect.*;
import java.util.*;

/**
 * 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 {
	private EditorPresentation editorPresentation;
	private WorkbenchWindow window;
	private WorkbenchPage page;
	private Map actionCache = new HashMap();

	private static final String RESOURCES_TO_SAVE_MESSAGE =
		WorkbenchMessages.getString("EditorManager.saveResourcesMessage"); //$NON-NLS-1$
	private static final String SAVE_RESOURCES_TITLE = WorkbenchMessages.getString("EditorManager.saveResourcesTitle"); //$NON-NLS-1$
/**
 * EditorManager constructor comment.
 */
public EditorManager(WorkbenchWindow window, WorkbenchPage workbenchPage, EditorPresentation pres) {
	this.window = window;
	this.page = workbenchPage;
	this.editorPresentation = pres;
}
/**
 * Closes all of the editors in the workbench.  The contents are not saved.
 *
 * This method will close the presentation for each editor.  
 * The IEditorPart.dispose method must be called at a higher level.
 */
public void closeAll() {
	// Close the pane, action bars, pane, etc.
	IEditorPart [] editors = editorPresentation.getEditors();
	editorPresentation.closeAllEditors();
	for (int nX = 0; nX < editors.length; nX ++) {
		IEditorPart part = editors[nX];
		PartSite site = (PartSite)part.getSite();
		disposeEditorActionBars((EditorActionBars)site.getActionBars());
		site.dispose();
	}
}
/**
 * Closes an editor.  The contents are not saved.
 *
 * This method will close the presentation for the editor.
 * The IEditorPart.dispose method must be called at a higher level.
 */
public void closeEditor(IEditorPart part) {
	// Close the pane, action bars, pane, etc.
	editorPresentation.closeEditor(part);
	PartSite site = (PartSite)part.getSite();
	disposeEditorActionBars((EditorActionBars)site.getActionBars());
	site.dispose();
}
/**
 * Answer a list of dirty editors.
 */
private List collectDirtyEditors(boolean closing) {
	List result = new ArrayList(3);
	IEditorPart [] editors = editorPresentation.getEditors();
	for (int nX = 0; nX < editors.length; nX ++) {
		IEditorPart part = editors[nX];
		if (closing) {
			if (part.isSaveOnCloseNeeded()) 
				result.add(part);
		} else {
			if (part.isDirty()) 
				result.add(part);
		}
	}
	return result;
}
/**
 * Returns whether the manager contains an editor.
 */
public boolean containsEditor(IEditorPart part) {
	IEditorPart [] editors = editorPresentation.getEditors();
	for (int nX = 0; nX < editors.length; nX ++) {
		if (part == editors[nX])
			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(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);
	}

	// Read action extensions.
	EditorActionBuilder builder = new EditorActionBuilder();
	contr = builder.readActionExtensions(desc, actionBars);
	if (contr != null) {
		actionBars.setExtensionContributor(contr);
		contr.init(actionBars);
	}

	// 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(page.getActionBars(), type);
	actionBars.addRef();
	actionCache.put(type, actionBars);
		
	// Return action bars.
	return actionBars;
}
/*
 * Dispose
 */
private void disposeEditorActionBars(EditorActionBars actionBars) {
	actionBars.removeRef();
	if (actionBars.getRef() <= 0) {
		String type = actionBars.getEditorType();
		actionCache.remove(type);
		actionBars.dispose();
	}
}
/*
 * Answer an open editor for the input element.  If none
 * exists return null.
 */
public IEditorPart findEditor(IEditorInput input) {
	IEditorPart [] editors = editorPresentation.getEditors();
	for (int nX = 0; nX < editors.length; nX ++) {
		IEditorPart part = editors[nX];
		if (input.equals(part.getEditorInput()))
			return part;
	}
	return null;
}
/**
 * Returns the SWT Display.
 */
private Display getDisplay() {
	return window.getShell().getDisplay();
}
/**
 * Answer the number of editors.
 */
public int getEditorCount() {
	IEditorPart [] editors = editorPresentation.getEditors();
	return editors.length;
}
/*
 * Answer the editor registry.
 */
private IEditorRegistry getEditorRegistry() {
	return WorkbenchPlugin.getDefault().getEditorRegistry();
}
/*
 * See IWorkbenchPage.
 */
public IEditorPart [] getEditors() {
	return editorPresentation.getEditors();
}
/*
 * See IWorkbenchPage#getFocusEditor
 */
public IEditorPart getVisibleEditor() {
	return editorPresentation.getVisibleEditor();
}
/**
 * Answer true if save is needed in any one of the editors.
 */
public boolean isSaveAllNeeded() {
	IEditorPart [] editors = editorPresentation.getEditors();
	for (int nX = 0; nX < editors.length; nX ++) {
		IEditorPart part = editors[nX];
		if (part.isDirty())
			return true;
	}
	return false;
}
/*
 * See IWorkbenchPage.
 */
public IEditorPart openEditor(String editorID, IEditorInput input) 
	throws PartInitException
{
	IEditorRegistry reg = getEditorRegistry();
	EditorDescriptor desc = (EditorDescriptor)reg.findEditor(editorID);
	if (desc == null) {
		throw new PartInitException(WorkbenchMessages.format("EditorManager.unknownEditorIDMessage", new Object[] {editorID})); //$NON-NLS-1$
	}
	return openEditor(desc, input);
}
/*
 * @see IWorkbenchPage.
 */
public IEditorPart openEditor(IFileEditorInput input) throws PartInitException {
	return openEditor(input,true);
}
/*
 * @see IWorkbenchPage.
 */
private IEditorPart openEditor(IFileEditorInput input,boolean setVisible) 
	throws PartInitException
{
	IFile file = input.getFile();
	// If there is a registered editor for the file use it.
	EditorDescriptor desc = (EditorDescriptor)getEditorRegistry().
		getDefaultEditor(file);
	if (desc != null) {
		return openEditor(desc, input);
	}

	// Try to open an OLE editor.
	IEditorPart componentEditor = ComponentSupport.getComponentEditor(file);
	if (componentEditor != null) {
		openInternalEditor(componentEditor, null, input,setVisible,null);
		return componentEditor;
	}

	// Try to open a system editor.
	if (testForSystemEditor(file)) {
		openSystemEditor(file);
		return null;
	}

	// There is no registered editor.  
	// Use the default text editor.
	desc = (EditorDescriptor)getEditorRegistry().getDefaultEditor();
	return openEditor(desc, input);
}

/*
 *
 */
private IReusableEditor findReusableEditor(EditorDescriptor desc) {
	
	IPreferenceStore store = WorkbenchPlugin.getDefault().getPreferenceStore();
	boolean reuseEditors = store.getBoolean(IPreferenceConstants.REUSE_EDITORS);
	if(!reuseEditors)
		return null;
	
	IEditorPart editors[] = getEditors();
	IReusableEditor dirtyEditor = null;
	IWorkbenchPart activePart = page.getActivePart();
	//Find IReusableEditor with the same descriptor id.
	for(int i = 0;i < editors.length;i++) {
		IEditorPart editor = editors[i];
		if(editor == activePart)
			continue;
		if(!(editor instanceof IReusableEditor))
			continue;
		IReusableEditor reusableEditor = (IReusableEditor)editor;
		if(!reusableEditor.getReuseEditor())
			continue;
		IEditorInput editorInput = reusableEditor.getEditorInput(); 
		EditorSite site = (EditorSite)reusableEditor.getEditorSite();
		EditorDescriptor oldDesc = site.getEditorDescriptor();
		if(oldDesc == null)
			oldDesc = (EditorDescriptor)getEditorRegistry().getDefaultEditor();
		if(desc.getId().equals(oldDesc.getId())) {
			if(editor.isDirty()) {
				dirtyEditor = reusableEditor;
				continue;
			}
			return reusableEditor;
		}
	}
	if(dirtyEditor == null)
		return null;
	
	//Should we have a global preference "Open new Editor when dirty"?
	//if(openNewWhenDirty)
	//	return null;
	MessageDialog dialog = new MessageDialog(
		window.getShell(),
		"Reusing dirty editor", 
		null,	// accept the default window icon
		dirtyEditor.getEditorInput().getName() + " has being modified. Save changes?", 
		MessageDialog.QUESTION, 
		new String[] {IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL,"Open new editor"}, 
		0);
	int result = dialog.open();
	if(result == 0) { //YES
		ProgressMonitorDialog pmd = new ProgressMonitorDialog(dialog.getShell());
		pmd.open();
		dirtyEditor.doSave(pmd.getProgressMonitor());
		pmd.close();
	} else if(result == 2) {
		return null;
	}
	return dirtyEditor;
}
/*
 * See IWorkbenchPage.
 */
private IEditorPart openEditor(EditorDescriptor desc, IEditorInput input)
	throws PartInitException {
	if (desc.isInternal()) {
		IReusableEditor reusableEditor = findReusableEditor(desc);
		if(reusableEditor != null) {
			reusableEditor.setInput(input);
			// Record the happy event.
			Workbench wb = (Workbench)window.getWorkbench();
			wb.getEditorHistory().add(input, desc);
			return reusableEditor;
		}
		return openInternalEditor(desc, input, true,null);
	} else
		if (desc.isOpenInPlace()) {
			IEditorPart editor = ComponentSupport.getComponentEditor();
			if (editor == null)
				return null;
			else {
				openInternalEditor(editor, desc, input, true,null);
				return editor;
			}
		} else
			if (desc.getId().equals(IWorkbenchConstants.SYSTEM_EDITOR_ID)) {
				if (input instanceof IFileEditorInput) {
					openSystemEditor(((IFileEditorInput) input).getFile());
					return null;
				} else
					throw new PartInitException(WorkbenchMessages.getString("EditorManager.systemEditorError")); //$NON-NLS-1$
			} else {
				openExternalEditor(desc, input);
				return null;
			}
}
/**
 * Open an external viewer on an file.  Throw up an error dialog if
 * an exception occurs.
 */
private void openExternalEditor(final EditorDescriptor desc, final Object input)
	throws PartInitException
{
	// Convert input to file.
	if (!(input instanceof IFileEditorInput))
		throw new PartInitException(WorkbenchMessages.format("EditorManager.errorOpeningExternalEditor", new Object[] {desc.getFileName(),desc.getId() }));  //$NON-NLS-1$
			
	final IFileEditorInput fileInput = (IFileEditorInput)input;
	
	//Must catch CoreException inside the runnable because
	//the Runnable.run() does not throw exceptions.
	final CoreException ex[] = new CoreException[1];
	// Start busy indicator.
	BusyIndicator.showWhile(getDisplay(), new Runnable() {
		public void run() {
			// Open an external editor.
			try {
				if (desc.getLauncher() != null) {
					// Open using launcher
					Object launcher = WorkbenchPlugin.createExtension(
						desc.getConfigurationElement(), "launcher");//$NON-NLS-1$
					((IEditorLauncher)launcher).open(fileInput.getFile());
				} else {	
					// Open using command
					ExternalEditor oEditor = new ExternalEditor(fileInput.getFile(), desc);
					oEditor.open();
				}
			} catch (CoreException e) {
				ex[0] = e;
			}
		}
	});
	
	// Test the result.
	if (ex[0] != null) {
		throw new PartInitException(WorkbenchMessages.format("EditorManager.errorInitializingExternalEditor", new Object[] {desc.getFileName(),desc.getId(),ex[0]})); //$NON-NLS-1$
	}
}
/*
 * Opens an editor part.
 */
private void openInternalEditor(final IEditorPart part, final EditorDescriptor desc,
	final IEditorInput input,final boolean setVisible,final IMemento memento) throws PartInitException
{
	//Must catch PartInitException inside the runnable because
	//the Runnable.run() does not throw exceptions.
	final PartInitException ex[] = new PartInitException[1];
	
	// Start busy indicator.
	BusyIndicator.showWhile(getDisplay(), new Runnable() {
		public void run() {
			try {
				// Create the site, action bars, pane, etc.
				EditorSite site = new EditorSite(part, page, desc,memento);
				part.init(site, input);
				if (part.getSite() != site)
					throw new PartInitException(WorkbenchMessages.format("EditorManager.siteIncorrect", new Object[] { desc.getId()})); //$NON-NLS-1$
					
				// Create the pane, action bars, etc.
				if (desc != null)
					site.setActionBars(createEditorActionBars(desc));
				else
					site.setActionBars(createEmptyEditorActionBars());
				editorPresentation.openEditor(part,setVisible);

				// Record the happy event.
				Workbench wb = (Workbench)window.getWorkbench();
				wb.getEditorHistory().add(input, desc);
			} catch (PartInitException e) {
				ex[0] = e;
			}
		}
	});

	// If the opening failed for any reason throw an exception.
	if (ex[0] != null) throw ex[0];
}
/**
 * Open an internal editor on an file.  Throw up an error dialog if
 * an exception occurs.
 */
private IEditorPart openInternalEditor(final EditorDescriptor desc, IEditorInput input,boolean setVisible,IMemento memento) 
	throws PartInitException
{
	// Create an editor instance.
	final IEditorPart editor[] = new IEditorPart[1];
	final Throwable ex[] = new Exception[1];
	Platform.run(new SafeRunnableAdapter() {
		public void run() throws CoreException {
			editor[0] = (IEditorPart) WorkbenchPlugin.createExtension(
				desc.getConfigurationElement(), "class");//$NON-NLS-1$
		}
		public void handleException(Throwable e) {
			ex[0] = e;
		}
	});
	
	if(ex[0] != null)
		throw new PartInitException(WorkbenchMessages.format("EditorManager.unableToInstantiate", new Object[] {desc.getId(),ex[0]})); //$NON-NLS-1$
	 
	// Open the instance.
	openInternalEditor(editor[0], desc, input,setVisible,memento);
	return editor[0];
}
/**
 * Open a system editor on the input file.  Throw up an error dialog if
 * an error occurs.
 */
public void openSystemEditor(final IFile input) throws PartInitException {
	// Start busy indicator.
	final boolean result[] = new boolean[1];
	BusyIndicator.showWhile(getDisplay(), new Runnable() {
		public void run() {
			// Open file using shell.
			String path = input.getLocation().toOSString();
			result[0] = Program.launch(path);
		}
	});

	// ShellExecute returns whether call was successful
	if (!result[0]) {
		throw new PartInitException(
			WorkbenchMessages.format("EditorManager.unableToOpenExternalEditor", new Object[] {input.getName()})); //$NON-NLS-1$
	}
}
/**
 * @see IPersistablePart
 */
public void restoreState(IMemento memento) {
	// Restore the editor area workbooks layout/relationship
	
	final String activeWorkbookID[] = new String[1];
	final ArrayList activeEditors = new ArrayList(5);
	final IEditorPart activeEditor[] = new IEditorPart[1];
	
	IMemento areaMem = memento.getChild(IWorkbenchConstants.TAG_AREA);
	if (areaMem != null) {
		editorPresentation.restoreState(areaMem);
		activeWorkbookID[0] = areaMem.getString(IWorkbenchConstants.TAG_ACTIVE_WORKBOOK);
	}
	
	// Loop through the editors.
	final int errors[] = new int[1];
	IMemento [] editors = memento.getChildren(IWorkbenchConstants.TAG_EDITOR);
	for (int x = 0; x < editors.length; x ++) {
		final IMemento editorMem = editors[x];
		Platform.run(new SafeRunnableAdapter() {
			public void run() {
				// Get the input factory.
				IMemento inputMem = editorMem.getChild(IWorkbenchConstants.TAG_INPUT);
				String factoryID = inputMem.getString(IWorkbenchConstants.TAG_FACTORY_ID);
				if (factoryID == null) {
					WorkbenchPlugin.log("Unable to restore editor - no input factory ID.");//$NON-NLS-1$
					errors[0]++;
					return;
				}
				IElementFactory factory = WorkbenchPlugin.getDefault().getElementFactory(factoryID);
				if (factory == null) {
					WorkbenchPlugin.log("Unable to restore editor - cannot instantiate input factory: " + factoryID);//$NON-NLS-1$
					errors[0]++;
					return;
				}
			
				// Get the input element.
				IAdaptable input = factory.createElement(inputMem);
				if (input == null) {
					WorkbenchPlugin.log("Unable to restore editor - cannot instantiate input element: " + factoryID);//$NON-NLS-1$
					return;
				}
				if (!(input instanceof IEditorInput)) {
					WorkbenchPlugin.log("Unable to restore editor - input is not IEditorInput");//$NON-NLS-1$
					errors[0]++;
					return;
				}
				IEditorInput editorInput = (IEditorInput)input;

				// Get the editor descriptor.
				String editorID = editorMem.getString(IWorkbenchConstants.TAG_ID);
				EditorDescriptor desc = null;
				if (editorID != null) {
					IEditorRegistry reg = WorkbenchPlugin.getDefault().getEditorRegistry();
					desc = (EditorDescriptor)reg.findEditor(editorID);
				}

				// Open the editor.
				try {
					String workbookID = editorMem.getString(IWorkbenchConstants.TAG_WORKBOOK);
					editorPresentation.setActiveEditorWorkbookFromID(workbookID);
					IEditorPart part;
					if(desc == null) 
						part = openEditor((IFileEditorInput)editorInput,false);
					else
						part = openInternalEditor(desc, editorInput,false,editorMem);
						
					String strFocus = editorMem.getString(IWorkbenchConstants.TAG_FOCUS);
					if ("true".equals(strFocus))//$NON-NLS-1$
						activeEditors.add(part);
					String strActivePart = editorMem.getString(IWorkbenchConstants.TAG_ACTIVE_PART);
					if ("true".equals(strActivePart))//$NON-NLS-1$
						activeEditor[0] = part;
				} catch (PartInitException e) {
					WorkbenchPlugin.log("Exception creating editor: " + e.getMessage());//$NON-NLS-1$
					errors[0]++;
				}
			}
			public void handleException(Throwable e) {
				errors[0]++;
			}
		});
	}

	Platform.run(new SafeRunnableAdapter() {
		public void run() {
			// Update each workbook with its visible editor.
			for (int i = 0; i < activeEditors.size(); i++)
				setVisibleEditor((IEditorPart)activeEditors.get(i), false);
				
			// Update the active workbook
			if (activeWorkbookID[0] != null)
				editorPresentation.setActiveEditorWorkbookFromID(activeWorkbookID[0]);

			if(activeEditor[0] != null)
				page.activate(activeEditor[0]);
		}
		public void handleException(Throwable e) {
			errors[0]++;
		}
	});
	
	if(errors[0] > 0) {
		String message = WorkbenchMessages.getString("EditorManager.multipleErrorsRestoring"); //$NON-NLS-1$
		if(errors[0] == 1)
			message = WorkbenchMessages.getString("EditorManager.oneErrorRestoring"); //$NON-NLS-1$
		MessageDialog.openError(null, WorkbenchMessages.getString("Error"), message); //$NON-NLS-1$
	}
}
/**
 * Runs a progress monitor operation.
 * Returns true if success, false if cancelled.
 */
private boolean runProgressMonitorOperation(String opName, 
	IRunnableWithProgress progressOp) 
{
	ProgressMonitorDialog dlg = new ProgressMonitorDialog(window.getShell());
	try {
		dlg.run(false, true, progressOp);
	} catch (InvocationTargetException e) {
		String title = WorkbenchMessages.format("EditorManager.operationFailed", new Object[] {opName}); //$NON-NLS-1$
		Throwable targetExc = e.getTargetException();
		WorkbenchPlugin.log(title, new Status(Status.WARNING, PlatformUI.PLUGIN_ID, 0, 
			title, targetExc));
		MessageDialog.openError(window.getShell(), WorkbenchMessages.getString("Error"),  //$NON-NLS-1$
			title + ':' + targetExc.getMessage());
	} catch (InterruptedException e) {
		// Ignore.  We run in current thread.
	}
	return !dlg.getProgressMonitor().isCanceled();
}
/**
 * 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.  If it is
	// empty just return.
	List dirtyEditors = collectDirtyEditors(closing);
	if (dirtyEditors.size() == 0)
		return true;

	// If confirmation is required ..
	if (confirm) {
		// Convert the list into an element collection.
		AdaptableList input = new AdaptableList();
		input.add(dirtyEditors.iterator());

		ListSelectionDialog dlg =
			new YesNoCancelListSelectionDialog(
				window.getShell(),
				input,
				new WorkbenchContentProvider(),
				new WorkbenchPartLabelProvider(),
				RESOURCES_TO_SAVE_MESSAGE);

		dlg.setInitialSelections(dirtyEditors.toArray(new Object[dirtyEditors.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;

		//Just return true but doing nothing if they chose not to save
		if (result == IDialogConstants.NO_ID)
			return true;

		dirtyEditors = Arrays.asList(dlg.getResult());
		if (dirtyEditors == null)
			return false;

		// If the editor list is empty return.
		if (dirtyEditors.size() == 0)
			return true;
	}

	// Create save block.
	final List finalEditors = dirtyEditors;
	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 {
				IProgressMonitor monitorWrap = new EventLoopProgressMonitor(monitor);
				ResourcesPlugin.getWorkspace().run(workspaceOp, monitorWrap);
			} 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$
				MessageDialog.openError(
					window.getShell(),
					WorkbenchMessages.getString("Error"), //$NON-NLS-1$
					WorkbenchMessages.format("EditorManager.saveFailedMessage", new Object[] {e.getMessage()})); //$NON-NLS-1$
			}
		}
	};

	// Do the save.
	return runProgressMonitorOperation(WorkbenchMessages.getString("Save_All"), progressOp); //$NON-NLS-1$
}
/**
 * Save and close an editor.
 * Return true if successful.  Return false if the
 * user has cancelled the command.
 */
public boolean saveEditor(final IEditorPart part, boolean confirm) {
	// Short circuit.
	if (!part.isDirty())
		return true;
		
	// If confirmation is required ..
	if (confirm) {

		String message = WorkbenchMessages.format("EditorManager.saveChangesQuestion", new Object[] {part.getTitle()}); //$NON-NLS-1$
		// Show a dialog.
		String [] buttons= new String[] { 
			IDialogConstants.YES_LABEL,
			IDialogConstants.NO_LABEL,
			IDialogConstants.CANCEL_LABEL
		};
		MessageDialog d= new MessageDialog(
			window.getShell(),
			WorkbenchMessages.getString("Save_Resource"), //$NON-NLS-1$
			null,
			message,
			MessageDialog.QUESTION,
			buttons,
			0
		);
		int choice = d.open();

		// Branch on the user choice.
		// The choice id is based on the order of button labels above.
		switch (choice) {
			case 0:   	//yes
				break;
			case 1:		//no
				return true;
			default:
			case 2:		//cancel
				return false;
		}
	}

	// Create save block.
	IRunnableWithProgress progressOp = new IRunnableWithProgress() {
		public void run(IProgressMonitor monitor) {
			IProgressMonitor monitorWrap = new EventLoopProgressMonitor(monitor);
			part.doSave(monitorWrap);
		}
	};

	// Do the save.
	return runProgressMonitorOperation(WorkbenchMessages.getString("Save"), progressOp); //$NON-NLS-1$
}
/**
 * @see IPersistablePart
 */
public void saveState(final IMemento memento) {
	// Save the editor area workbooks layout/relationship
	IMemento editorAreaMem = memento.createChild(IWorkbenchConstants.TAG_AREA);
	editorPresentation.saveState(editorAreaMem);

	// Save the active workbook id
	editorAreaMem.putString(IWorkbenchConstants.TAG_ACTIVE_WORKBOOK, editorPresentation.getActiveEditorWorkbookID());
	
	// Save each open editor.
	IEditorPart [] editors = getEditors();
	final int errors[] = new int[1];
	for (int x = 0; x < editors.length; x ++) {
		final IEditorPart editor = editors[x];
		Platform.run(new SafeRunnableAdapter() {
			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_ID, editor.getSite().getId());

				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().getVisibleEditor())
					editorMem.putString(IWorkbenchConstants.TAG_FOCUS, "true");//$NON-NLS-1$

				// Save input.
				IMemento inputMem = editorMem.createChild(IWorkbenchConstants.TAG_INPUT);
				inputMem.putString(IWorkbenchConstants.TAG_FACTORY_ID, persistable.getFactoryId());
				persistable.saveState(inputMem);
				((EditorSite)editor.getEditorSite()).saveState(editorMem);
				
			}
			public void handleException(Throwable e) {
				errors[0]++;
			}
		});
	}
	if(errors[0] > 0) {
		String message = WorkbenchMessages.getString("EditorManager.multipleErrors"); //$NON-NLS-1$
		if(errors[0] == 1)
			message = WorkbenchMessages.getString("EditorManager.oneError"); //$NON-NLS-1$
		MessageDialog.openError(null, WorkbenchMessages.getString("Error"), message); //$NON-NLS-1$
	}

}
/**
 * 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(IEditorPart newEd, boolean setFocus) {
	return editorPresentation.setVisibleEditor(newEd, setFocus);
}
/**
 * Answer true if a system editor exists for the input file.
 * @see openSystemEditor.
 */
private boolean testForSystemEditor(IFile input) {
	String strName = input.getName();
	int nDot = strName.lastIndexOf('.');
	if (nDot >= 0) {
		strName = strName.substring(nDot);
		return Program.findProgram(strName) != null;
	}
	return false;
}
}
