diff options
| author | Paul Webster | 2013-05-14 16:16:06 +0000 |
|---|---|---|
| committer | Paul Webster | 2013-05-23 16:05:50 +0000 |
| commit | e41dbc7b42e73b036f7e54669e0197b3554ec0e2 (patch) | |
| tree | 74308e88cd41a2f49b610135f142bf8f235943a7 | |
| parent | cbcfb2fc143bf90b639cedcf8c1acaab21089cef (diff) | |
| download | eclipse.platform.ui-e41dbc7b42e73b036f7e54669e0197b3554ec0e2.tar.gz eclipse.platform.ui-e41dbc7b42e73b036f7e54669e0197b3554ec0e2.tar.xz eclipse.platform.ui-e41dbc7b42e73b036f7e54669e0197b3554ec0e2.zip | |
Bug 405562 - Save All saves only the selected Saveables in a
ISaveablePart
A different approach, go through the ui.workbench saveable code.
Change-Id: I82aa5c52c35e43a4fcf9d9f07174b495418786f8
13 files changed, 786 insertions, 181 deletions
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/WBWRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/WBWRenderer.java index 044723dd685..5f06e43a77e 100644 --- a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/WBWRenderer.java +++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/WBWRenderer.java @@ -25,6 +25,7 @@ import org.eclipse.e4.core.services.events.IEventBroker; import org.eclipse.e4.core.services.log.Logger; import org.eclipse.e4.ui.internal.workbench.Activator; import org.eclipse.e4.ui.internal.workbench.E4Workbench; +import org.eclipse.e4.ui.internal.workbench.PartServiceSaveHandler; import org.eclipse.e4.ui.internal.workbench.Policy; import org.eclipse.e4.ui.model.application.MApplication; import org.eclipse.e4.ui.model.application.ui.MContext; @@ -460,7 +461,7 @@ public class WBWRenderer extends SWTPartRenderer { return wbwShell; } }); - localContext.set(ISaveHandler.class, new ISaveHandler() { + final PartServiceSaveHandler saveHandler = new PartServiceSaveHandler() { public Save promptToSave(MPart dirtyPart) { Shell shell = (Shell) context .get(IServiceConstants.ACTIVE_SHELL); @@ -488,7 +489,9 @@ public class WBWRenderer extends SWTPartRenderer { } return response; } - }); + }; + saveHandler.logger = logger; + localContext.set(ISaveHandler.class, saveHandler); if (wbwModel.getLabel() != null) wbwShell.setText(wbwModel.getLocalizedLabel()); diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceImpl.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceImpl.java index ea87aee6706..a5c3383eb1f 100644 --- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceImpl.java +++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceImpl.java @@ -54,7 +54,6 @@ import org.eclipse.e4.ui.workbench.modeling.EModelService; import org.eclipse.e4.ui.workbench.modeling.EPartService; import org.eclipse.e4.ui.workbench.modeling.IPartListener; import org.eclipse.e4.ui.workbench.modeling.ISaveHandler; -import org.eclipse.e4.ui.workbench.modeling.ISaveHandler.Save; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.osgi.util.NLS; @@ -1207,15 +1206,8 @@ public class PartServiceImpl implements EPartService { return true; } - if (confirm && saveHandler != null) { - switch (saveHandler.promptToSave(part)) { - case NO: - return true; - case CANCEL: - return false; - case YES: - break; - } + if (saveHandler != null) { + return saveHandler.save(part, confirm); } Object client = part.getObject(); @@ -1238,25 +1230,8 @@ public class PartServiceImpl implements EPartService { if (dirtyParts.isEmpty()) { return true; } - - if (confirm && saveHandler != null) { - List<MPart> dirtyPartsList = Collections.unmodifiableList(new ArrayList<MPart>( - dirtyParts)); - Save[] decisions = saveHandler.promptToSave(dirtyPartsList); - for (Save decision : decisions) { - if (decision == Save.CANCEL) { - return false; - } - } - - for (int i = 0; i < decisions.length; i++) { - if (decisions[i] == Save.YES) { - if (!savePart(dirtyPartsList.get(i), false)) { - return false; - } - } - } - return true; + if (saveHandler != null) { + return saveHandler.saveParts(dirtyParts, confirm); } for (MPart dirtyPart : dirtyParts) { diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceSaveHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceSaveHandler.java new file mode 100644 index 00000000000..9d68c8fe93a --- /dev/null +++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/PartServiceSaveHandler.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2013 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.e4.ui.internal.workbench; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.eclipse.e4.core.contexts.ContextInjectionFactory; +import org.eclipse.e4.core.di.InjectionException; +import org.eclipse.e4.core.services.log.Logger; +import org.eclipse.e4.ui.di.Persist; +import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.workbench.modeling.ISaveHandler; +import org.eclipse.osgi.util.NLS; + +public class PartServiceSaveHandler implements ISaveHandler { + + public Logger logger; + + private void log(String unidentifiedMessage, String identifiedMessage, String id, Exception e) { + if (logger == null) { + return; + } + if (id == null || id.length() == 0) { + logger.error(e, unidentifiedMessage); + } else { + logger.error(e, NLS.bind(identifiedMessage, id)); + } + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.e4.ui.workbench.modeling.ISaveHandler#save(org.eclipse.e4.ui.model.application + * .ui.basic.MPart, boolean) + */ + public boolean save(MPart dirtyPart, boolean confirm) { + if (confirm) { + switch (promptToSave(dirtyPart)) { + case NO: + return true; + case CANCEL: + return false; + case YES: + break; + } + } + + Object client = dirtyPart.getObject(); + try { + ContextInjectionFactory.invoke(client, Persist.class, dirtyPart.getContext()); + } catch (InjectionException e) { + log("Failed to persist contents of part", "Failed to persist contents of part ({0})", //$NON-NLS-1$ //$NON-NLS-2$ + dirtyPart.getElementId(), e); + return false; + } catch (RuntimeException e) { + log("Failed to persist contents of part via DI", //$NON-NLS-1$ + "Failed to persist contents of part ({0}) via DI", dirtyPart.getElementId(), e); //$NON-NLS-1$ + return false; + } + return true; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.e4.ui.workbench.modeling.ISaveHandler#saveParts(java.util.Collection, + * boolean) + */ + public boolean saveParts(Collection<MPart> dirtyParts, boolean confirm) { + if (confirm) { + List<MPart> dirtyPartsList = Collections.unmodifiableList(new ArrayList<MPart>( + dirtyParts)); + Save[] decisions = promptToSave(dirtyPartsList); + for (Save decision : decisions) { + if (decision == Save.CANCEL) { + return false; + } + } + + for (int i = 0; i < decisions.length; i++) { + if (decisions[i] == Save.YES) { + if (!save(dirtyPartsList.get(i), false)) { + return false; + } + } + } + return true; + } + + for (MPart dirtyPart : dirtyParts) { + if (!save(dirtyPart, false)) { + return false; + } + } + return true; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.e4.ui.workbench.modeling.ISaveHandler#promptToSave(org.eclipse.e4.ui.model. + * application.ui.basic.MPart) + */ + public Save promptToSave(MPart dirtyPart) { + return Save.YES; + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.e4.ui.workbench.modeling.ISaveHandler#promptToSave(java.util.Collection) + */ + public Save[] promptToSave(Collection<MPart> dirtyParts) { + Save[] rc = new Save[dirtyParts.size()]; + for (int i = 0; i < rc.length; i++) { + rc[i] = Save.YES; + } + return rc; + } + +} diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ISaveHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ISaveHandler.java index 5be71996d6f..5778847d170 100644 --- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ISaveHandler.java +++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/ISaveHandler.java @@ -20,6 +20,10 @@ public interface ISaveHandler { YES, NO, CANCEL } + public boolean save(MPart dirtyPart, boolean confirm); + + public boolean saveParts(Collection<MPart> dirtyParts, boolean confirm); + public Save promptToSave(MPart dirtyPart); public Save[] promptToSave(Collection<MPart> dirtyParts); diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/SaveAction.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/SaveAction.java index e677c6f1c4b..677b3fa1830 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/SaveAction.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/SaveAction.java @@ -17,6 +17,7 @@ import org.eclipse.ui.ISaveablesSource; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.IWorkbenchCommandConstants; import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; /** @@ -65,9 +66,15 @@ public class SaveAction extends BaseSaveAction implements IBackgroundSaveListene */ ISaveablePart saveView = getSaveableView(); if (saveView != null) { - ((WorkbenchPage) getActivePart().getSite().getPage()).saveSaveable(saveView, false, - false); - return; + IWorkbenchPart activePart = getActivePart(); + WorkbenchPage workbenchPage; + if (activePart != null) { + workbenchPage = (WorkbenchPage) activePart.getSite().getPage(); + } else { + workbenchPage = (WorkbenchPage) getActivePage(); + } + workbenchPage.saveSaveable(saveView, activePart, false, false); + return; } IEditorPart part = getActiveEditor(); diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/SaveableHelper.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/SaveableHelper.java index d524c078971..1f753a91d8a 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/SaveableHelper.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/SaveableHelper.java @@ -17,7 +17,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; - import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -183,20 +182,23 @@ public class SaveableHelper { public void run(IProgressMonitor monitor) { IProgressMonitor monitorWrap = new EventLoopProgressMonitor(monitor); monitorWrap.beginTask(WorkbenchMessages.Save, dirtyModels.size()); - for (Iterator i = dirtyModels.iterator(); i.hasNext();) { - Saveable model = (Saveable) i.next(); - // handle case where this model got saved as a result of saving another - if (!model.isDirty()) { - monitor.worked(1); - continue; - } - doSaveModel(model, new SubProgressMonitor(monitorWrap, 1), - window, confirm); - if (monitor.isCanceled()) { - break; + try { + for (Iterator i = dirtyModels.iterator(); i.hasNext();) { + Saveable model = (Saveable) i.next(); + // handle case where this model got saved as a result of + // saving another + if (!model.isDirty()) { + monitor.worked(1); + continue; + } + doSaveModel(model, new SubProgressMonitor(monitorWrap, 1), window, confirm); + if (monitor.isCanceled()) { + break; + } } + } finally { + monitorWrap.done(); } - monitorWrap.done(); } }; diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java index b224db2bf99..c8f2473b5d5 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java @@ -1139,7 +1139,7 @@ public final class Workbench extends EventManager implements IWorkbench { for (IWorkbenchWindow window : getWorkbenchWindows()) { IWorkbenchPage page = window.getActivePage(); if (page != null) { - if (!((WorkbenchPage) page).saveAllEditors(confirm, closing)) { + if (!((WorkbenchPage) page).saveAllEditors(confirm, closing, false)) { return false; } } diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPage.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPage.java index c7c5ee63555..8fff9f744b2 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPage.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPage.java @@ -22,6 +22,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -31,8 +32,10 @@ import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker; import org.eclipse.e4.core.contexts.ContextInjectionFactory; import org.eclipse.e4.core.contexts.IEclipseContext; @@ -62,22 +65,27 @@ import org.eclipse.e4.ui.workbench.UIEvents; import org.eclipse.e4.ui.workbench.modeling.EModelService; import org.eclipse.e4.ui.workbench.modeling.EPartService; import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState; -import org.eclipse.e4.ui.workbench.modeling.ISaveHandler; -import org.eclipse.e4.ui.workbench.modeling.ISaveHandler.Save; import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IPageChangeProvider; import org.eclipse.jface.dialogs.IPageChangedListener; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.PageChangedEvent; import org.eclipse.jface.internal.provisional.action.ICoolBarManager2; +import org.eclipse.jface.operation.IRunnableContext; +import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.util.SafeRunnable; +import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.window.IShellProvider; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DropTarget; @@ -106,7 +114,9 @@ import org.eclipse.ui.IPerspectiveFactory; import org.eclipse.ui.IPerspectiveRegistry; import org.eclipse.ui.IReusableEditor; import org.eclipse.ui.ISaveablePart; +import org.eclipse.ui.ISaveablePart2; import org.eclipse.ui.ISaveablesLifecycleListener; +import org.eclipse.ui.ISaveablesSource; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.ISelectionService; import org.eclipse.ui.IShowEditorInput; @@ -123,10 +133,13 @@ import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.MultiPartInitException; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.Saveable; import org.eclipse.ui.WorkbenchException; import org.eclipse.ui.XMLMemento; import org.eclipse.ui.contexts.IContextService; +import org.eclipse.ui.dialogs.ListSelectionDialog; import org.eclipse.ui.internal.dialogs.CustomizePerspectiveDialog; +import org.eclipse.ui.internal.dialogs.EventLoopProgressMonitor; import org.eclipse.ui.internal.e4.compatibility.CompatibilityEditor; import org.eclipse.ui.internal.e4.compatibility.CompatibilityPart; import org.eclipse.ui.internal.e4.compatibility.CompatibilityView; @@ -147,6 +160,7 @@ import org.eclipse.ui.internal.tweaklets.TabBehaviour; import org.eclipse.ui.internal.tweaklets.Tweaklets; import org.eclipse.ui.internal.util.Util; import org.eclipse.ui.model.IWorkbenchAdapter; +import org.eclipse.ui.model.WorkbenchPartLabelProvider; import org.eclipse.ui.part.IShowInSource; import org.eclipse.ui.part.ShowInContext; import org.eclipse.ui.views.IStickyViewDescriptor; @@ -1437,7 +1451,7 @@ public class WorkbenchPage extends CompatibleWorkbenchPage implements if (save) { if (workbenchPart instanceof ISaveablePart) { ISaveablePart saveablePart = (ISaveablePart) workbenchPart; - if (!saveSaveable(saveablePart, confirm, true)) { + if (!saveSaveable(saveablePart, workbenchPart, confirm, true)) { return false; } } @@ -1519,6 +1533,7 @@ public class WorkbenchPage extends CompatibleWorkbenchPage implements // check to ensure this perspective actually exists in this window if (persp != null) { if (saveParts) { + List<IWorkbenchPart> partsToSave = new ArrayList<IWorkbenchPart>(); // retrieve all parts under the specified perspective List<MPart> parts = modelService.findElements(persp, null, MPart.class, null); if (!parts.isEmpty()) { @@ -1543,6 +1558,8 @@ public class WorkbenchPage extends CompatibleWorkbenchPage implements if (!((ISaveablePart) workbenchPart).isSaveOnCloseNeeded()) { part.setDirty(false); it.remove(); + } else { + partsToSave.add(workbenchPart); } } } @@ -1551,32 +1568,10 @@ public class WorkbenchPage extends CompatibleWorkbenchPage implements } } - if (!parts.isEmpty()) { - ISaveHandler saveHandler = persp.getContext().get(ISaveHandler.class); - if (parts.size() == 1) { - Save responses = saveHandler.promptToSave(parts.get(0)); - switch (responses) { - case CANCEL: - return; - case NO: - break; - case YES: - partService.savePart(parts.get(0), false); - break; - } - } else { - Save[] responses = saveHandler.promptToSave(parts); - for (Save response : responses) { - if (response == Save.CANCEL) { - return; - } - } - - for (int i = 0; i < responses.length; i++) { - if (responses[i] == Save.YES) { - partService.savePart(parts.get(i), false); - } - } + if (!partsToSave.isEmpty()) { + if (!saveAll(partsToSave, true, true, false, legacyWindow, legacyWindow)) { + // user cancel + return; } } } @@ -1655,7 +1650,7 @@ public class WorkbenchPage extends CompatibleWorkbenchPage implements } private boolean close(boolean save, boolean unsetPage) { - if (save && !saveAllEditors(true, true)) { + if (save && !saveAllEditors(true, true, true)) { return false; } @@ -3178,6 +3173,7 @@ public class WorkbenchPage extends CompatibleWorkbenchPage implements } List<MPart> dirtyParts = new ArrayList<MPart>(); + List<IWorkbenchPart> partsToSave = new ArrayList<IWorkbenchPart>(); // iterate over the list of parts to find dirty parts for (MPart currentPart : perspectiveParts) { if (currentPart.isDirty()) { @@ -3185,63 +3181,40 @@ public class WorkbenchPage extends CompatibleWorkbenchPage implements if (object == null) { continue; } else if (object instanceof CompatibilityPart) { - CompatibilityPart compatibilityPart = (CompatibilityPart) object; - if (!((ISaveablePart) compatibilityPart.getPart()).isSaveOnCloseNeeded()) { + IWorkbenchPart workbenchPart = ((CompatibilityPart) object).getPart(); + if (!(workbenchPart instanceof ISaveablePart) + || !((ISaveablePart) workbenchPart).isSaveOnCloseNeeded()) { continue; } + partsToSave.add(workbenchPart); } dirtyParts.add(currentPart); } } - if (!dirtyParts.isEmpty()) { - ISaveHandler saveHandler = window.getContext().get(ISaveHandler.class); - if (dirtyParts.size() == 1) { - MPart part = dirtyParts.get(0); - switch (saveHandler.promptToSave(part)) { - case YES: - partService.savePart(part, false); - break; - case NO: - part.setDirty(false); - // not saving this part, close it - partService.hidePart(part); - break; - case CANCEL: - // not going through with it, but we're done - legacyWindow.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE); - return; - } - } else { - Save[] promptToSave = saveHandler.promptToSave(dirtyParts); - for (Save save : promptToSave) { - if (save == ISaveHandler.Save.CANCEL) { - // not going through with it, but we're done - legacyWindow.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE); - return; - } - } - - for (int i = 0; i < promptToSave.length; i++) { - switch (promptToSave[i]) { - case NO: - dirtyParts.get(i).setDirty(false); - // not saving this part, close it - partService.hidePart(dirtyParts.get(i)); - break; - case YES: - partService.savePart(dirtyParts.get(i), false); - break; - case CANCEL: - break; - } - } + SaveablesList saveablesList = null; + Object postCloseInfo = null; + if (partsToSave.size() > 0) { + saveablesList = (SaveablesList) getWorkbenchWindow().getService( + ISaveablesLifecycleListener.class); + postCloseInfo = saveablesList.preCloseParts(partsToSave, true, + this.getWorkbenchWindow()); + if (postCloseInfo == null) { + // cancel + // We're not going through with the reset, so it is + // complete. + legacyWindow.firePerspectiveChanged(this, desc, CHANGE_RESET_COMPLETE); + return; } } modelService.resetPerspectiveModel(persp, window); + if (saveablesList != null) { + saveablesList.postClose(postCloseInfo); + } + boolean revert = false; if (desc instanceof PerspectiveDescriptor) { PerspectiveDescriptor perspectiveDescriptor = (PerspectiveDescriptor) desc; @@ -3350,59 +3323,355 @@ public class WorkbenchPage extends CompatibleWorkbenchPage implements * See IWorkbenchPage */ public boolean saveAllEditors(boolean confirm) { - return saveAllEditors(confirm, false); + return saveAllEditors(confirm, false, false); } - boolean saveAllEditors(boolean confirm, boolean closing) { - List<MPart> dirtyParts = new ArrayList<MPart>(); - // find all the dirty parts in this window - for (MPart currentPart : modelService.findElements(window, null, MPart.class, null)) { - if (currentPart.isDirty()) { - Object object = currentPart.getObject(); - if (object == null) { - continue; - } else if (object instanceof CompatibilityPart) { - CompatibilityPart compatibilityPart = (CompatibilityPart) object; - if (closing - && !((ISaveablePart) compatibilityPart.getPart()).isSaveOnCloseNeeded()) { - continue; - } + public ISaveablePart[] getDirtyParts() { + List result = new ArrayList(3); + IWorkbenchPartReference[] allParts = getSortedParts(); + for (int i = 0; i < allParts.length; i++) { + IWorkbenchPartReference reference = allParts[i]; + + IWorkbenchPart part = reference.getPart(false); + if (part != null && part instanceof ISaveablePart) { + ISaveablePart saveable = (ISaveablePart) part; + if (saveable.isDirty()) { + result.add(saveable); } - - dirtyParts.add(currentPart); } } - if (!dirtyParts.isEmpty()) { - if (confirm) { - if (dirtyParts.size() == 1) { - return partService.savePart(dirtyParts.get(0), true); + return (ISaveablePart[]) result.toArray(new ISaveablePart[result.size()]); + } + + public boolean saveAllEditors(boolean confirm, boolean closing, boolean addNonPartSources) { + ISaveablePart[] parts = 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, closing, addNonPartSources, legacyWindow, legacyWindow); + } + + public static boolean saveAll(List dirtyParts, final boolean confirm, final boolean closing, + boolean addNonPartSources, final IRunnableContext runnableContext, + final IShellProvider shellProvider) { + // clone the input list + dirtyParts = new ArrayList(dirtyParts); + + if (closing) { + // if the parts are going to be closed, then we only save those that + // need to be saved when closed, see bug 272070 + for (Iterator it = dirtyParts.iterator(); it.hasNext();) { + ISaveablePart saveablePart = (ISaveablePart) it.next(); + if (!saveablePart.isSaveOnCloseNeeded()) { + it.remove(); } + } + } - ISaveHandler saveHandler = window.getContext().get(ISaveHandler.class); - Save[] promptToSave = saveHandler.promptToSave(dirtyParts); - for (Save save : promptToSave) { - if (save == ISaveHandler.Save.CANCEL) { + List modelsToSave; + if (confirm) { + boolean saveable2Processed = false; + // 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 + int choice = SaveableHelper.savePart((ISaveablePart2) part, + page.getWorkbenchWindow(), confirm); + if (choice == ISaveablePart2.CANCEL) { + // If the user cancels, don't restore the previous + // workbench state, as that will + // be an unexpected switch from the current state. return false; + } else if (choice != ISaveablePart2.DEFAULT) { + saveable2Processed = true; + listIterator.remove(); } } + } - for (int i = 0; i < promptToSave.length; i++) { - if (promptToSave[i] == Save.YES) { - if (!partService.savePart(dirtyParts.get(i), false)) { - return false; - } + // try to restore the workbench to its previous state + if (currentPage != null && currentPageOriginalPerspective != null) { + if (!currentPageOriginalPerspective.equals(currentPage.getActivePerspective())) { + currentPage.setPerspective(currentPageOriginalPerspective.getDesc()); + } + } + + // if processing a ISaveablePart2 caused other parts to be + // saved, remove them from the list presented to the user. + if (saveable2Processed) { + listIterator = dirtyParts.listIterator(); + while (listIterator.hasNext()) { + ISaveablePart part = (ISaveablePart) listIterator.next(); + if (!part.isDirty()) { + listIterator.remove(); + } + } + } + + modelsToSave = convertToSaveables(dirtyParts, closing, addNonPartSources); + + // If nothing to save, return. + if (modelsToSave.isEmpty()) { + return true; + } + boolean canceled = SaveableHelper.waitForBackgroundSaveJobs(modelsToSave); + if (canceled) { + return false; + } + // Use a simpler dialog if there's only one + if (modelsToSave.size() == 1) { + Saveable model = (Saveable) modelsToSave.get(0); + String message = NLS.bind(WorkbenchMessages.EditorManager_saveChangesQuestion, + model.getName()); + // Show a dialog. + String[] buttons = new String[] { IDialogConstants.YES_LABEL, + IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }; + MessageDialog d = new MessageDialog(shellProvider.getShell(), + WorkbenchMessages.Save_Resource, null, message, MessageDialog.QUESTION, + buttons, 0) { + protected int getShellStyle() { + return super.getShellStyle() | SWT.SHEET; } + }; + + int choice = SaveableHelper.testGetAutomatedResponse(); + if (SaveableHelper.testGetAutomatedResponse() == SaveableHelper.USER_RESPONSE) { + choice = d.open(); + } + + // Branch on the user choice. + // The choice id is based on the order of button labels + // above. + switch (choice) { + case ISaveablePart2.YES: // yes + break; + case ISaveablePart2.NO: // no + return true; + default: + case ISaveablePart2.CANCEL: // cancel + return false; } } else { - for (MPart part : dirtyParts) { - if (!partService.savePart(part, false)) { + ListSelectionDialog dlg = new ListSelectionDialog(shellProvider.getShell(), + modelsToSave, new ArrayContentProvider(), new WorkbenchPartLabelProvider(), + WorkbenchMessages.EditorManager_saveResourcesMessage) { + protected int getShellStyle() { + return super.getShellStyle() | SWT.SHEET; + } + }; + dlg.setInitialSelections(modelsToSave.toArray()); + dlg.setTitle(WorkbenchMessages.EditorManager_saveResourcesTitle); + + // this "if" statement aids in testing. + if (SaveableHelper.testGetAutomatedResponse() == SaveableHelper.USER_RESPONSE) { + int result = dlg.open(); + // Just return false to prevent the operation continuing + if (result == IDialogConstants.CANCEL_ID) { return false; } + + modelsToSave = Arrays.asList(dlg.getResult()); } } + } else { + modelsToSave = convertToSaveables(dirtyParts, closing, addNonPartSources); } - return true; + + // If the editor list is empty return. + if (modelsToSave.isEmpty()) { + return true; + } + + // Create save block. + final List finalModels = modelsToSave; + IRunnableWithProgress progressOp = new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) { + IProgressMonitor monitorWrap = new EventLoopProgressMonitor(monitor); + monitorWrap.beginTask(WorkbenchMessages.Saving_Modifications, finalModels.size()); + for (Iterator i = finalModels.iterator(); i.hasNext();) { + Saveable model = (Saveable) i.next(); + // handle case where this model got saved as a result of + // saving another + if (!model.isDirty()) { + monitor.worked(1); + continue; + } + SaveableHelper.doSaveModel(model, new SubProgressMonitor(monitorWrap, 1), + shellProvider, closing || confirm); + if (monitorWrap.isCanceled()) { + break; + } + } + monitorWrap.done(); + } + }; + + // Do the save. + return SaveableHelper.runProgressMonitorOperation(WorkbenchMessages.Save_All, progressOp, + runnableContext, shellProvider); + } + + /** + * For each part (view or editor) in the given list, attempts to convert it + * to one or more saveable models. Duplicate models are removed. If closing + * is true, then models that will remain open in parts other than the given + * parts are removed. + * + * @param parts + * the parts (list of IViewPart or IEditorPart) + * @param closing + * whether the parts are being closed + * @param addNonPartSources + * whether non-part sources should be added (true for the Save + * All action, see bug 139004) + * @return the dirty models + */ + private static List convertToSaveables(List parts, boolean closing, boolean addNonPartSources) { + ArrayList result = new ArrayList(); + HashSet seen = new HashSet(); + for (Iterator i = parts.iterator(); i.hasNext();) { + IWorkbenchPart part = (IWorkbenchPart) i.next(); + Saveable[] saveables = getSaveables(part); + for (int j = 0; j < saveables.length; j++) { + Saveable saveable = saveables[j]; + if (saveable.isDirty() && !seen.contains(saveable)) { + seen.add(saveable); + if (!closing + || closingLastPartShowingModel(saveable, parts, part.getSite() + .getPage())) { + result.add(saveable); + } + } + } + } + if (addNonPartSources) { + SaveablesList saveablesList = (SaveablesList) PlatformUI.getWorkbench().getService( + ISaveablesLifecycleListener.class); + ISaveablesSource[] nonPartSources = saveablesList.getNonPartSources(); + for (int i = 0; i < nonPartSources.length; i++) { + Saveable[] saveables = nonPartSources[i].getSaveables(); + for (int j = 0; j < saveables.length; j++) { + Saveable saveable = saveables[j]; + if (saveable.isDirty() && !seen.contains(saveable)) { + seen.add(saveable); + result.add(saveable); + } + } + } + } + return result; + } + + /** + * Returns the saveable models provided by the given part. If the part does + * not provide any models, a default model is returned representing the + * part. + * + * @param part + * the workbench part + * @return the saveable models + */ + private static Saveable[] getSaveables(IWorkbenchPart part) { + if (part instanceof ISaveablesSource) { + ISaveablesSource source = (ISaveablesSource) part; + return source.getSaveables(); + } + return new Saveable[] { new DefaultSaveable(part) }; + } + + /** + * Returns true if, in the given page, no more parts will reference the + * given model if the given parts are closed. + * + * @param model + * the model + * @param closingParts + * the parts being closed (list of IViewPart or IEditorPart) + * @param page + * the page + * @return <code>true</code> if no more parts in the page will reference the + * given model, <code>false</code> otherwise + */ + private static boolean closingLastPartShowingModel(Saveable model, List closingParts, + IWorkbenchPage page) { + HashSet closingPartsWithSameModel = new HashSet(); + for (Iterator i = closingParts.iterator(); i.hasNext();) { + IWorkbenchPart part = (IWorkbenchPart) i.next(); + Saveable[] models = getSaveables(part); + if (Arrays.asList(models).contains(model)) { + closingPartsWithSameModel.add(part); + } + } + IWorkbenchPartReference[] pagePartRefs = ((WorkbenchPage) page).getSortedParts(); + HashSet pagePartsWithSameModels = new HashSet(); + for (int i = 0; i < pagePartRefs.length; i++) { + IWorkbenchPartReference partRef = pagePartRefs[i]; + IWorkbenchPart part = partRef.getPart(false); + if (part != null) { + Saveable[] models = getSaveables(part); + if (Arrays.asList(models).contains(model)) { + pagePartsWithSameModels.add(part); + } + } + } + for (Iterator i = closingPartsWithSameModel.iterator(); i.hasNext();) { + IWorkbenchPart part = (IWorkbenchPart) i.next(); + pagePartsWithSameModels.remove(part); + } + return pagePartsWithSameModels.isEmpty(); } /** @@ -3422,24 +3691,9 @@ public class WorkbenchPage extends CompatibleWorkbenchPage implements * <code>false</code> otherwise * @see ISaveablePart#isSaveOnCloseNeeded() */ - public boolean saveSaveable(ISaveablePart saveable, boolean confirm, boolean closing) { - MPart part = findPart((IWorkbenchPart) saveable); - if (part != null) { - if (saveable.isDirty()) { - if (closing) { - if (saveable.isSaveOnCloseNeeded()) { - return partService.savePart(part, confirm); - } - // mark the part as no longer being dirty so it can be - // closed - part.setDirty(false); - } else { - return partService.savePart(part, confirm); - } - } - return true; - } - return false; + public boolean saveSaveable(ISaveablePart saveable, IWorkbenchPart part, boolean confirm, + boolean closing) { + return SaveableHelper.savePart(saveable, part, legacyWindow, confirm); } /** @@ -3452,7 +3706,7 @@ public class WorkbenchPage extends CompatibleWorkbenchPage implements * if the user cancels the command */ public boolean saveEditor(IEditorPart editor, boolean confirm) { - return saveSaveable(editor, confirm, false); + return saveSaveable(editor, editor, confirm, false); } /* diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java index e780a8c764d..067f47998db 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java @@ -42,7 +42,10 @@ import org.eclipse.e4.core.contexts.ContextInjectionFactory; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.e4.core.contexts.RunAndTrack; import org.eclipse.e4.core.di.InjectionException; +import org.eclipse.e4.core.di.annotations.Optional; import org.eclipse.e4.core.services.events.IEventBroker; +import org.eclipse.e4.core.services.log.Logger; +import org.eclipse.e4.ui.internal.workbench.PartServiceSaveHandler; import org.eclipse.e4.ui.internal.workbench.URIHelper; import org.eclipse.e4.ui.internal.workbench.renderers.swt.IUpdateService; import org.eclipse.e4.ui.model.application.MApplication; @@ -205,6 +208,10 @@ public class WorkbenchWindow implements IWorkbenchWindow { private IEventBroker eventBroker; @Inject + @Optional + private Logger logger; + + @Inject private IExtensionRegistry extensionRegistry; private WorkbenchPage page; @@ -447,7 +454,7 @@ public class WorkbenchWindow implements IWorkbenchWindow { }); final ISaveHandler defaultSaveHandler = windowContext.get(ISaveHandler.class); - windowContext.set(ISaveHandler.class, new ISaveHandler() { + final PartServiceSaveHandler localSaveHandler = new PartServiceSaveHandler() { public Save promptToSave(MPart dirtyPart) { Object object = dirtyPart.getObject(); if (object instanceof CompatibilityPart) { @@ -493,7 +500,39 @@ public class WorkbenchWindow implements IWorkbenchWindow { } return retSaves; } - }); + + public boolean save(MPart dirtyPart, boolean confirm) { + Object object = dirtyPart.getObject(); + if (object instanceof CompatibilityPart) { + IWorkbenchPart workbenchPart = ((CompatibilityPart) object).getPart(); + if (workbenchPart instanceof ISaveablePart) { + ISaveablePart saveablePart = (ISaveablePart) workbenchPart; + return page.saveSaveable(saveablePart, workbenchPart, confirm, false); + } + } + return super.save(dirtyPart, confirm); + } + + public boolean saveParts(Collection<MPart> dirtyParts, boolean confirm) { + ArrayList<ISaveablePart> saveables = new ArrayList<ISaveablePart>(); + for (MPart part : dirtyParts) { + Object object = part.getObject(); + if (object instanceof CompatibilityPart) { + IWorkbenchPart workbenchPart = ((CompatibilityPart) object).getPart(); + if (workbenchPart instanceof ISaveablePart) { + saveables.add((ISaveablePart) workbenchPart); + } + } + } + if (saveables.isEmpty()) { + return super.saveParts(dirtyParts, confirm); + } + return WorkbenchPage.saveAll(saveables, confirm, false, true, WorkbenchWindow.this, + WorkbenchWindow.this); + } + }; + localSaveHandler.logger = logger; + windowContext.set(ISaveHandler.class, localSaveHandler); windowContext.set(IWorkbenchWindow.class.getName(), this); windowContext.set(IPageService.class, this); @@ -1561,7 +1600,7 @@ public class WorkbenchWindow implements IWorkbenchWindow { if (!getWorkbenchImpl().isClosing()) { IWorkbenchPage page = getActivePage(); if (page != null) { - return ((WorkbenchPage) page).saveAllEditors(true, true); + return ((WorkbenchPage) page).saveAllEditors(true, true, true); } } return true; diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/handlers/SaveAllHandler.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/handlers/SaveAllHandler.java new file mode 100644 index 00000000000..e12d3cfe028 --- /dev/null +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/handlers/SaveAllHandler.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2013 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.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.core.expressions.EvaluationResult; +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.ui.ISaveablesLifecycleListener; +import org.eclipse.ui.ISaveablesSource; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.Saveable; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.internal.InternalHandlerUtil; +import org.eclipse.ui.internal.SaveablesList; +import org.eclipse.ui.internal.WorkbenchPage; + +/** + * Saves all active editors + * <p> + * Replacement for SaveAllAction + * </p> + * + * @since 3.7 + * + */ +public class SaveAllHandler extends AbstractSaveHandler { + + public SaveAllHandler() { + registerEnablement(); + } + + public Object execute(ExecutionEvent event) throws ExecutionException { + IWorkbenchWindow window = HandlerUtil + .getActiveWorkbenchWindowChecked(event); + IWorkbenchPage page = window.getActivePage(); + if (page != null) { + ((WorkbenchPage) page).saveAllEditors(false, false, true); + } + + return null; + } + + protected EvaluationResult evaluate(IEvaluationContext context) { + + IWorkbenchWindow window = InternalHandlerUtil.getActiveWorkbenchWindow(context); + // no window? not active + if (window == null) + return EvaluationResult.FALSE; + WorkbenchPage page = (WorkbenchPage) window.getActivePage(); + + // no page? not active + if (page == null) + return EvaluationResult.FALSE; + + // if at least one dirty part, then we are active + if (page.getDirtyParts().length > 0) + return EvaluationResult.TRUE; + + // Since Save All also saves saveables from non-part sources, + // look if any such saveables exist and are dirty. + SaveablesList saveablesList = (SaveablesList) window.getWorkbench().getService( + ISaveablesLifecycleListener.class); + ISaveablesSource[] nonPartSources = saveablesList.getNonPartSources(); + for (int i = 0; i < nonPartSources.length; i++) { + Saveable[] saveables = nonPartSources[i].getSaveables(); + for (int j = 0; j < saveables.length; j++) { + if (saveables[j].isDirty()) { + return EvaluationResult.TRUE; + } + } + } + + // if nothing, then we are not active + return EvaluationResult.FALSE; + } + +} diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/handlers/SaveHandler.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/handlers/SaveHandler.java new file mode 100644 index 00000000000..a57fad52d86 --- /dev/null +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/handlers/SaveHandler.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2013 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.handlers; + +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.expressions.EvaluationResult; +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.ISaveablePart; +import org.eclipse.ui.ISaveablesSource; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.handlers.HandlerUtil; +import org.eclipse.ui.internal.InternalHandlerUtil; +import org.eclipse.ui.internal.SaveableHelper; +import org.eclipse.ui.internal.WorkbenchPage; + +/** + * <p> + * Replacement for SaveAction + * </p> + * + * @since 3.7 + * + */ +public class SaveHandler extends AbstractSaveHandler { + + public SaveHandler() { + registerEnablement(); + } + + public Object execute(ExecutionEvent event) { + + ISaveablePart saveablePart = getSaveablePart(event); + + // no saveable + if (saveablePart == null) + return null; + + // if editor + if (saveablePart instanceof IEditorPart) { + IEditorPart editorPart = (IEditorPart) saveablePart; + IWorkbenchPage page = editorPart.getSite().getPage(); + page.saveEditor(editorPart, false); + return null; + } + + // if view + IWorkbenchPart activePart = HandlerUtil.getActivePart(event); + WorkbenchPage page = (WorkbenchPage) activePart.getSite().getPage(); + page.saveSaveable(saveablePart, activePart, false, false); + + return null; + + } + + protected EvaluationResult evaluate(IEvaluationContext context) { + + IWorkbenchWindow window = InternalHandlerUtil.getActiveWorkbenchWindow(context); + // no window? not active + if (window == null) + return EvaluationResult.FALSE; + WorkbenchPage page = (WorkbenchPage) window.getActivePage(); + + // no page? not active + if (page == null) + return EvaluationResult.FALSE; + + // get saveable part + ISaveablePart saveablePart = getSaveablePart(context); + if (saveablePart == null) + return EvaluationResult.FALSE; + + if (saveablePart instanceof ISaveablesSource) { + ISaveablesSource modelSource = (ISaveablesSource) saveablePart; + if (SaveableHelper.needsSave(modelSource)) + return EvaluationResult.TRUE; + return EvaluationResult.FALSE; + } + + if (saveablePart != null && saveablePart.isDirty()) + return EvaluationResult.TRUE; + + return EvaluationResult.FALSE; + } +} diff --git a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/application/EPartServiceTest.java b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/application/EPartServiceTest.java index 1089b7a1913..c0cde535e5f 100644 --- a/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/application/EPartServiceTest.java +++ b/tests/org.eclipse.e4.ui.tests/src/org/eclipse/e4/ui/tests/application/EPartServiceTest.java @@ -20,6 +20,7 @@ import org.eclipse.core.runtime.AssertionFailedException; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.e4.ui.di.Focus; import org.eclipse.e4.ui.internal.workbench.E4Workbench; +import org.eclipse.e4.ui.internal.workbench.PartServiceSaveHandler; import org.eclipse.e4.ui.internal.workbench.UIEventPublisher; import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor; import org.eclipse.e4.ui.model.application.ui.MElementContainer; @@ -3786,7 +3787,7 @@ public class EPartServiceTest extends UITest { editor.setThrowException(throwException); window.getContext().set(ISaveHandler.class.getName(), - new ISaveHandler() { + new PartServiceSaveHandler() { public Save[] promptToSave(Collection<MPart> saveablePart) { return null; } @@ -4111,7 +4112,7 @@ public class EPartServiceTest extends UITest { editor2.setThrowException(throwException[1]); window.getContext().set(ISaveHandler.class.getName(), - new ISaveHandler() { + new PartServiceSaveHandler() { public Save[] promptToSave(Collection<MPart> saveableParts) { int index = 0; Save[] prompt = new Save[saveableParts.size()]; @@ -10160,7 +10161,7 @@ public class EPartServiceTest extends UITest { new UIEventPublisher(applicationContext)); applicationContext.set(ISaveHandler.class.getName(), - new ISaveHandler() { + new PartServiceSaveHandler() { public Save[] promptToSave(Collection<MPart> saveablePart) { Save[] ret = new Save[saveablePart.size()]; Arrays.fill(ret, ISaveHandler.Save.YES); @@ -10170,6 +10171,7 @@ public class EPartServiceTest extends UITest { public Save promptToSave(MPart saveablePart) { return ISaveHandler.Save.YES; } + }); } diff --git a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/api/APITestUtils.java b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/api/APITestUtils.java index f47bd3eb0b4..c2822d8ca0d 100644 --- a/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/api/APITestUtils.java +++ b/tests/org.eclipse.ui.tests/Eclipse UI Tests/org/eclipse/ui/tests/api/APITestUtils.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Map; import org.eclipse.e4.core.contexts.IEclipseContext; +import org.eclipse.e4.ui.internal.workbench.PartServiceSaveHandler; import org.eclipse.e4.ui.model.application.MApplication; import org.eclipse.e4.ui.model.application.ui.MUIElement; import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder; @@ -27,6 +28,7 @@ import org.eclipse.e4.ui.workbench.modeling.ISaveHandler; import org.eclipse.ui.ISaveablePart2; import org.eclipse.ui.IViewReference; import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.internal.SaveableHelper; import org.eclipse.ui.internal.Workbench; import org.eclipse.ui.internal.WorkbenchPartReference; @@ -34,7 +36,7 @@ public class APITestUtils { private static Map<IEclipseContext, ISaveHandler> originalHandlers = new HashMap<IEclipseContext, ISaveHandler>(); private static TestSaveHandler testSaveHandler = new TestSaveHandler(); - static class TestSaveHandler implements ISaveHandler { + static class TestSaveHandler extends PartServiceSaveHandler { private int response; public void setResponse(int response) { @@ -58,6 +60,7 @@ public class APITestUtils { Arrays.fill(prompt, save); return prompt; } + } public static boolean isFastView(IViewReference ref) { @@ -79,6 +82,7 @@ public class APITestUtils { } public static void saveableHelperSetAutomatedResponse(final int response) { + SaveableHelper.testSetAutomatedResponse(response); Workbench workbench = (Workbench) PlatformUI.getWorkbench(); MApplication application = workbench.getApplication(); |
