diff options
| author | Tristan Hume | 2013-02-07 16:11:25 +0000 |
|---|---|---|
| committer | Paul Webster | 2013-02-08 16:33:01 +0000 |
| commit | 5996d971b066df1e44667a78d815e81dd312c54c (patch) | |
| tree | 6561ef1a85b703ddec2c9f962a434c0f5ccebbb1 | |
| parent | af7488841db9f606ba6d5de93ed5615adb7f08e8 (diff) | |
| download | eclipse.platform.ui-5996d971b066df1e44667a78d815e81dd312c54c.tar.gz eclipse.platform.ui-5996d971b066df1e44667a78d815e81dd312c54c.tar.xz eclipse.platform.ui-5996d971b066df1e44667a78d815e81dd312c54c.zip | |
Bug 2369 - [Workbench] Would like to be able to save workspace without exitingv20130208-163301
Copy the model, clean it up, and then write it out.
15 files changed, 486 insertions, 91 deletions
diff --git a/bundles/org.eclipse.e4.ui.model.workbench/model/UIElements.ecore b/bundles/org.eclipse.e4.ui.model.workbench/model/UIElements.ecore index b30b80d39d5..213ec6aaebd 100644 --- a/bundles/org.eclipse.e4.ui.model.workbench/model/UIElements.ecore +++ b/bundles/org.eclipse.e4.ui.model.workbench/model/UIElements.ecore @@ -409,6 +409,8 @@ <eClassifiers xsi:type="ecore:EClass" name="WindowElement" abstract="true" interface="true"
eSuperTypes="#//ui/UIElement"/>
<eClassifiers xsi:type="ecore:EClass" name="TrimBar">
+ <eStructuralFeatures xsi:type="ecore:EReference" name="pendingCleanup" upperBound="-1"
+ eType="#//ui/basic/TrimElement" transient="true"/>
<eGenericSuperTypes eClassifier="#//ui/GenericTrimContainer">
<eTypeArguments eClassifier="#//ui/basic/TrimElement"/>
</eGenericSuperTypes>
diff --git a/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/application/ui/basic/MTrimBar.java b/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/application/ui/basic/MTrimBar.java index 42c840f5e9d..e5d4215ce50 100644 --- a/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/application/ui/basic/MTrimBar.java +++ b/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/application/ui/basic/MTrimBar.java @@ -10,6 +10,7 @@ */ package org.eclipse.e4.ui.model.application.ui.basic; +import java.util.List; import org.eclipse.e4.ui.model.application.ui.MGenericTrimContainer; import org.eclipse.e4.ui.model.application.ui.MUIElement; @@ -18,9 +19,30 @@ import org.eclipse.e4.ui.model.application.ui.MUIElement; * A representation of the model object '<em><b>Trim Bar</b></em>'. * <!-- end-user-doc --> * + * <p> + * The following features are supported: + * <ul> + * <li>{@link org.eclipse.e4.ui.model.application.ui.basic.MTrimBar#getPendingCleanup <em>Pending Cleanup</em>}</li> + * </ul> + * </p> * * @model * @generated */ public interface MTrimBar extends MGenericTrimContainer<MTrimElement>, MUIElement { + + /** + * Returns the value of the '<em><b>Pending Cleanup</b></em>' reference list. + * The list contents are of type {@link org.eclipse.e4.ui.model.application.ui.basic.MTrimElement}. + * <!-- begin-user-doc --> + * <p> + * If the meaning of the '<em>Pending Cleanup</em>' reference list isn't clear, + * there really should be more of a description here... + * </p> + * <!-- end-user-doc --> + * @return the value of the '<em>Pending Cleanup</em>' reference list. + * @model transient="true" + * @generated + */ + List<MTrimElement> getPendingCleanup(); } // MTrimBar diff --git a/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/application/ui/basic/impl/BasicPackageImpl.java b/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/application/ui/basic/impl/BasicPackageImpl.java index 8a4e6c76040..a30b87e9ae9 100644 --- a/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/application/ui/basic/impl/BasicPackageImpl.java +++ b/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/application/ui/basic/impl/BasicPackageImpl.java @@ -2562,13 +2562,22 @@ public class BasicPackageImpl extends EPackageImpl { public static final int TRIM_BAR__SIDE = UiPackageImpl.GENERIC_TRIM_CONTAINER__SIDE; /** + * The feature id for the '<em><b>Pending Cleanup</b></em>' reference list. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + public static final int TRIM_BAR__PENDING_CLEANUP = UiPackageImpl.GENERIC_TRIM_CONTAINER_FEATURE_COUNT + 0; + + /** * The number of structural features of the '<em>Trim Bar</em>' class. * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated * @ordered */ - public static final int TRIM_BAR_FEATURE_COUNT = UiPackageImpl.GENERIC_TRIM_CONTAINER_FEATURE_COUNT + 0; + public static final int TRIM_BAR_FEATURE_COUNT = UiPackageImpl.GENERIC_TRIM_CONTAINER_FEATURE_COUNT + 1; /** * The operation id for the '<em>Get Localized Accessibility Phrase</em>' operation. @@ -3201,6 +3210,20 @@ public class BasicPackageImpl extends EPackageImpl { } /** + * Returns the meta object for the reference list '{@link org.eclipse.e4.ui.model.application.ui.basic.MTrimBar#getPendingCleanup <em>Pending Cleanup</em>}'. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @return the meta object for the reference list '<em>Pending Cleanup</em>'. + * @see org.eclipse.e4.ui.model.application.ui.basic.MTrimBar#getPendingCleanup() + * @see #getTrimBar() + * @generated + */ + public EReference getTrimBar_PendingCleanup() { + return (EReference)trimBarEClass.getEStructuralFeatures().get(0); + } + + + /** * Returns the meta object for class '{@link org.eclipse.e4.ui.model.application.ui.basic.MStackElement <em>Stack Element</em>}'. * <!-- begin-user-doc --> * <!-- end-user-doc --> @@ -3275,6 +3298,7 @@ public class BasicPackageImpl extends EPackageImpl { windowElementEClass = createEClass(WINDOW_ELEMENT); trimBarEClass = createEClass(TRIM_BAR); + createEReference(trimBarEClass, TRIM_BAR__PENDING_CLEANUP); stackElementEClass = createEClass(STACK_ELEMENT); } @@ -3401,6 +3425,7 @@ public class BasicPackageImpl extends EPackageImpl { initEClass(windowElementEClass, MWindowElement.class, "WindowElement", IS_ABSTRACT, IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); //$NON-NLS-1$ initEClass(trimBarEClass, MTrimBar.class, "TrimBar", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); //$NON-NLS-1$ + initEReference(getTrimBar_PendingCleanup(), this.getTrimElement(), null, "pendingCleanup", null, 0, -1, MTrimBar.class, IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); //$NON-NLS-1$ initEClass(stackElementEClass, MStackElement.class, "StackElement", IS_ABSTRACT, IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); //$NON-NLS-1$ } @@ -3623,6 +3648,14 @@ public class BasicPackageImpl extends EPackageImpl { public static final EClass TRIM_BAR = eINSTANCE.getTrimBar(); /** + * The meta object literal for the '<em><b>Pending Cleanup</b></em>' reference list feature. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public static final EReference TRIM_BAR__PENDING_CLEANUP = eINSTANCE.getTrimBar_PendingCleanup(); + + /** * The meta object literal for the '{@link org.eclipse.e4.ui.model.application.ui.basic.MStackElement <em>Stack Element</em>}' class. * <!-- begin-user-doc --> * <!-- end-user-doc --> diff --git a/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/application/ui/basic/impl/TrimBarImpl.java b/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/application/ui/basic/impl/TrimBarImpl.java index 55c3d5871de..e569e762240 100644 --- a/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/application/ui/basic/impl/TrimBarImpl.java +++ b/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/application/ui/basic/impl/TrimBarImpl.java @@ -10,22 +10,40 @@ */ package org.eclipse.e4.ui.model.application.ui.basic.impl; +import java.util.Collection; +import java.util.List; import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar; import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement; import org.eclipse.e4.ui.model.application.ui.impl.GenericTrimContainerImpl; +import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.util.EObjectResolvingEList; /** * <!-- begin-user-doc --> * An implementation of the model object '<em><b>Trim Bar</b></em>'. * <!-- end-user-doc --> * <p> + * The following features are implemented: + * <ul> + * <li>{@link org.eclipse.e4.ui.model.application.ui.basic.impl.TrimBarImpl#getPendingCleanup <em>Pending Cleanup</em>}</li> + * </ul> * </p> * * @generated */ public class TrimBarImpl extends GenericTrimContainerImpl<MTrimElement> implements MTrimBar { /** + * The cached value of the '{@link #getPendingCleanup() <em>Pending Cleanup</em>}' reference list. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getPendingCleanup() + * @generated + * @ordered + */ + protected EList<MTrimElement> pendingCleanup; + + /** * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated @@ -44,4 +62,76 @@ public class TrimBarImpl extends GenericTrimContainerImpl<MTrimElement> implemen return BasicPackageImpl.Literals.TRIM_BAR; } + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public List<MTrimElement> getPendingCleanup() { + if (pendingCleanup == null) { + pendingCleanup = new EObjectResolvingEList<MTrimElement>(MTrimElement.class, this, BasicPackageImpl.TRIM_BAR__PENDING_CLEANUP); + } + return pendingCleanup; + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + @Override + public Object eGet(int featureID, boolean resolve, boolean coreType) { + switch (featureID) { + case BasicPackageImpl.TRIM_BAR__PENDING_CLEANUP: + return getPendingCleanup(); + } + return super.eGet(featureID, resolve, coreType); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + @SuppressWarnings("unchecked") + @Override + public void eSet(int featureID, Object newValue) { + switch (featureID) { + case BasicPackageImpl.TRIM_BAR__PENDING_CLEANUP: + getPendingCleanup().clear(); + getPendingCleanup().addAll((Collection<? extends MTrimElement>)newValue); + return; + } + super.eSet(featureID, newValue); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + @Override + public void eUnset(int featureID) { + switch (featureID) { + case BasicPackageImpl.TRIM_BAR__PENDING_CLEANUP: + getPendingCleanup().clear(); + return; + } + super.eUnset(featureID); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + @Override + public boolean eIsSet(int featureID) { + switch (featureID) { + case BasicPackageImpl.TRIM_BAR__PENDING_CLEANUP: + return pendingCleanup != null && !pendingCleanup.isEmpty(); + } + return super.eIsSet(featureID); + } + } //TrimBarImpl diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimBarRenderer.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimBarRenderer.java index 69cadb9fe5d..a50636bd959 100644 --- a/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimBarRenderer.java +++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt/src/org/eclipse/e4/ui/workbench/renderers/swt/TrimBarRenderer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2010 IBM Corporation and others. + * Copyright (c) 2009, 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 @@ -7,12 +7,14 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Tristan Hume - <trishume@gmail.com> - + * Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting + * Implemented workbench auto-save to correctly restore state in case of crash. ******************************************************************************/ package org.eclipse.e4.ui.workbench.renderers.swt; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import org.eclipse.e4.core.contexts.IEclipseContext; @@ -69,8 +71,6 @@ public class TrimBarRenderer extends SWTPartRenderer { } } - private HashMap<MTrimBar, ArrayList<ArrayList<MTrimElement>>> pendingCleanup = new HashMap<MTrimBar, ArrayList<ArrayList<MTrimElement>>>(); - /* * (non-Javadoc) * @@ -210,13 +210,7 @@ public class TrimBarRenderer extends SWTPartRenderer { } }); } - ArrayList<ArrayList<MTrimElement>> lists = pendingCleanup - .get(trimModel); - if (lists == null) { - lists = new ArrayList<ArrayList<MTrimElement>>(); - pendingCleanup.put(trimModel, lists); - } - lists.add(toRemove); + trimModel.getPendingCleanup().addAll(toRemove); } } // We're done if the retryList is now empty (everything done) or @@ -226,16 +220,14 @@ public class TrimBarRenderer extends SWTPartRenderer { } } + /** + * @param element + * the trimBar to be cleaned up + */ protected void cleanUp(MTrimBar element) { - ArrayList<ArrayList<MTrimElement>> lists = pendingCleanup - .remove(element); - if (lists == null) { - return; - } - for (ArrayList<MTrimElement> list : lists) { - for (MTrimElement child : list) { - element.getChildren().remove(child); - } + for (MTrimElement child : element.getPendingCleanup()) { + element.getChildren().remove(child); } + element.getPendingCleanup().clear(); } } diff --git a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Application.java b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Application.java index c344cc75d8c..1cf2bdabf45 100644 --- a/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Application.java +++ b/bundles/org.eclipse.e4.ui.workbench.swt/src/org/eclipse/e4/ui/internal/workbench/swt/E4Application.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2012 IBM Corporation and others. + * Copyright (c) 2009, 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 @@ -7,6 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Tristan Hume - <trishume@gmail.com> - + * Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting + * Implemented workbench auto-save to correctly restore state in case of crash. ******************************************************************************/ package org.eclipse.e4.ui.internal.workbench.swt; @@ -366,6 +369,7 @@ public class E4Application implements IApplication { handler = (IModelResourceHandler) factory.create(resourceHandler, eclipseContext); + eclipseContext.set(IModelResourceHandler.class, handler); Resource resource = handler.loadMostRecentModel(); theApp = (MApplication) resource.getContents().get(0); diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ResourceHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ResourceHandler.java index 2cccdc4e326..2e361fa7839 100644 --- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ResourceHandler.java +++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ResourceHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2012 IBM Corporation and others. + * Copyright (c) 2009, 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 @@ -7,6 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Tristan Hume - <trishume@gmail.com> - + * Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting + * Implemented workbench auto-save to correctly restore state in case of crash. ******************************************************************************/ package org.eclipse.e4.ui.internal.workbench; @@ -122,16 +125,7 @@ public class ResourceHandler implements IModelResourceHandler { } public Resource loadMostRecentModel() { - File baseLocation; - try { - baseLocation = new File(URIUtil.toURI(instanceLocation.getURL())); - } catch (URISyntaxException e) { - throw new RuntimeException(e); - } - baseLocation = new File(baseLocation, ".metadata"); //$NON-NLS-1$ - baseLocation = new File(baseLocation, ".plugins"); //$NON-NLS-1$ - baseLocation = new File(baseLocation, "org.eclipse.e4.workbench"); //$NON-NLS-1$ - + File baseLocation = getBaseLocation(); // This is temporary code to migrate existing delta files into full models if (deltaRestore && saveAndRestore && !clearPersistedState) { File deltaFile = new File(baseLocation, "deltas.xml"); //$NON-NLS-1$ @@ -139,7 +133,7 @@ public class ResourceHandler implements IModelResourceHandler { MApplication appElement = null; try { // create new resource in case code below fails somewhere - File workbenchData = new File(baseLocation, "workbench.xmi"); //$NON-NLS-1$ + File workbenchData = getWorkbenchSaveLocation(); URI restoreLocationNew = URI.createFileURI(workbenchData.getAbsolutePath()); resource = resourceSetImpl.createResource(restoreLocationNew); @@ -179,7 +173,7 @@ public class ResourceHandler implements IModelResourceHandler { } } - File workbenchData = new File(baseLocation, "workbench.xmi"); //$NON-NLS-1$ + File workbenchData = getWorkbenchSaveLocation(); if (clearPersistedState && workbenchData.exists()) workbenchData.delete(); @@ -204,10 +198,7 @@ public class ResourceHandler implements IModelResourceHandler { if (resource == null) { Resource applicationResource = loadResource(applicationDefinitionInstance); MApplication theApp = (MApplication) applicationResource.getContents().get(0); - if (restoreLocation == null) - restoreLocation = URI.createFileURI(workbenchData.getAbsolutePath()); - resource = resourceSetImpl.createResource(restoreLocation); - resource.getContents().add((EObject) theApp); + resource = createResourceWithApp(theApp); } // Add model items described in the model extension point @@ -227,6 +218,38 @@ public class ResourceHandler implements IModelResourceHandler { resource.save(null); } + /** + * Creates a resource with an app Model, used for saving copies of the main app model. + * + * @param theApp + * the application model to add to the resource + * @return a resource with a proper save path with the model as contents + */ + public Resource createResourceWithApp(MApplication theApp) { + URI saveLocation = URI.createFileURI(getWorkbenchSaveLocation().getAbsolutePath()); + Resource res = resourceSetImpl.createResource(saveLocation); + res.getContents().add((EObject) theApp); + return res; + } + + private File getWorkbenchSaveLocation() { + File workbenchData = new File(getBaseLocation(), "workbench.xmi"); //$NON-NLS-1$ + return workbenchData; + } + + private File getBaseLocation() { + File baseLocation; + try { + baseLocation = new File(URIUtil.toURI(instanceLocation.getURL())); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + baseLocation = new File(baseLocation, ".metadata"); //$NON-NLS-1$ + baseLocation = new File(baseLocation, ".plugins"); //$NON-NLS-1$ + baseLocation = new File(baseLocation, "org.eclipse.e4.workbench"); //$NON-NLS-1$ + return baseLocation; + } + // Ensures that even models with error are loaded! private Resource loadResource(URI uri) { Resource resource; diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IModelResourceHandler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IModelResourceHandler.java index e69831b54ce..955020845aa 100644 --- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IModelResourceHandler.java +++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/IModelResourceHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 IBM Corporation and others. + * Copyright (c) 2010,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 @@ -7,11 +7,15 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Tristan Hume - <trishume@gmail.com> - + * Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting + * Implemented workbench auto-save to correctly restore state in case of crash. ******************************************************************************/ package org.eclipse.e4.ui.workbench; import java.io.IOException; +import org.eclipse.e4.ui.model.application.MApplication; import org.eclipse.emf.ecore.resource.Resource; /** @@ -25,6 +29,15 @@ public interface IModelResourceHandler { Resource loadMostRecentModel(); /** + * Creates a resource with an app Model, used for saving copies of the main app model. + * + * @param theApp + * the application model to add to the resource + * @return a resource with a proper save path with the model as contents + */ + public Resource createResourceWithApp(MApplication theApp); + + /** * @throws IOException * if storing fails * diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/IDEWorkbenchPreferencePage.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/IDEWorkbenchPreferencePage.java index 4b571aabf19..72be43dd3e8 100644 --- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/IDEWorkbenchPreferencePage.java +++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/dialogs/IDEWorkbenchPreferencePage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. + * Copyright (c) 2000, 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 @@ -7,6 +7,9 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Tristan Hume - <trishume@gmail.com> - + * Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting + * Implemented workbench auto-save to correctly restore state in case of crash. *******************************************************************************/ package org.eclipse.ui.internal.ide.dialogs; @@ -40,10 +43,7 @@ public class IDEWorkbenchPreferencePage extends WorkbenchPreferencePage Composite composite = createComposite(parent); - createShowUserDialogPref(composite); - createStickyCyclePref(composite); - createHeapStatusPref(composite); - + createSettings(composite); createOpenModeGroup(composite); applyDialogFont(composite); diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/IPreferenceConstants.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/IPreferenceConstants.java index b23d975568f..2d40a81defb 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/IPreferenceConstants.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/IPreferenceConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 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 @@ -8,6 +8,9 @@ * Contributors: * IBM Corporation - initial API and implementation * Semion Chichelnitsky (semion@il.ibm.com) - bug 278064 + * Tristan Hume - <trishume@gmail.com> - + * Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting + * Implemented workbench auto-save to correctly restore state in case of crash. *******************************************************************************/ package org.eclipse.ui.internal; @@ -234,4 +237,13 @@ public interface IPreferenceConstants { */ public static final String USE_32_THREADING = "use32Threading"; //$NON-NLS-1$ + /** + * Preference value that specifies the time interval in minutes between + * workbench auto-saves. If the value is zero it disables workbench + * auto-save. + * + * @since 3.105 + */ + public static final String WORKBENCH_SAVE_INTERVAL = "WORKBENCH_SAVE_INTERVAL"; //$NON-NLS-1$ + } 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 a96c2c236aa..9763f8304d2 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 @@ -9,6 +9,9 @@ * IBM Corporation - initial API and implementation * Francis Upton - <francisu@ieee.org> - * Fix for Bug 217777 [Workbench] Workbench event loop does not terminate if Display is closed + * Tristan Hume - <trishume@gmail.com> - + * Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting + * Implemented workbench auto-save to correctly restore state in case of crash. *******************************************************************************/ package org.eclipse.ui.internal; @@ -81,12 +84,18 @@ import org.eclipse.e4.ui.model.application.commands.impl.CommandsFactoryImpl; import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor; import org.eclipse.e4.ui.model.application.ui.MElementContainer; import org.eclipse.e4.ui.model.application.ui.basic.MPart; +import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar; +import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement; +import org.eclipse.e4.ui.model.application.ui.basic.MTrimmedWindow; import org.eclipse.e4.ui.model.application.ui.basic.MWindow; import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicFactoryImpl; import org.eclipse.e4.ui.services.EContextService; +import org.eclipse.e4.ui.workbench.IModelResourceHandler; import org.eclipse.e4.ui.workbench.IPresentationEngine; import org.eclipse.e4.ui.workbench.UIEvents; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; import org.eclipse.jface.action.ActionContributionItem; @@ -217,6 +226,7 @@ import org.eclipse.ui.menus.IMenuService; import org.eclipse.ui.model.IContributionService; import org.eclipse.ui.operations.IWorkbenchOperationSupport; import org.eclipse.ui.progress.IProgressService; +import org.eclipse.ui.progress.WorkbenchJob; import org.eclipse.ui.services.IDisposable; import org.eclipse.ui.services.IEvaluationService; import org.eclipse.ui.services.IServiceScopes; @@ -429,6 +439,8 @@ public final class Workbench extends EventManager implements IWorkbench { private Listener backForwardListener; + private Job autoSaveJob; + /** * Creates a new workbench. * @@ -1019,6 +1031,12 @@ public final class Workbench extends EventManager implements IWorkbench { if (!force && !isClosing) { return false; } + + // stop the workbench auto-save job so it can't conflict with shutdown + if(autoSaveJob != null) { + autoSaveJob.cancel(); + autoSaveJob = null; + } boolean closeEditors = !force && PrefUtil.getAPIPreferenceStore().getBoolean( @@ -1040,7 +1058,65 @@ public final class Workbench extends EventManager implements IWorkbench { } } - // discard editors that with non-ppersistable inputs + // persist editor inputs and close editors that can't be persisted + // also persists views + persist(true); + + if (!force && !isClosing) { + return false; + } + + SafeRunner.run(new SafeRunnable(WorkbenchMessages.ErrorClosing) { + public void run() { + if (isClosing || force) { + // isClosing = windowManager.close(); + E4Util.unsupported("Need to close since no windowManager"); //$NON-NLS-1$ + MWindow selectedWindow = application.getSelectedElement(); + WorkbenchWindow selected = null; + for (IWorkbenchWindow window : getWorkbenchWindows()) { + WorkbenchWindow ww = (WorkbenchWindow) window; + if (ww.getModel() == selectedWindow) { + selected = ww; + } else { + ((WorkbenchWindow) window).close(false); + } + } + + if (selected != null) { + selected.close(false); + } + + windowsClosed = true; + } + } + }); + + if (!force && !isClosing) { + return false; + } + + shutdown(); + + IPresentationEngine engine = application.getContext().get(IPresentationEngine.class); + engine.stop(); + //System.err.println("stop()"); //$NON-NLS-1$ + + runEventLoop = false; + return true; + } + + /** + * Saves the state of the workbench in the same way that closing the it + * would. Can be called while the editor is running so that if it crashes + * the workbench state can be recovered. + * + * @param shutdown + * If true, will close any editors that cannot be persisted. Will + * also skip saving the model to the disk since that is done + * later in shutdown. + */ + private void persist(final boolean shutdown) { + // persist editors that can be and possibly close the others SafeRunner.run(new SafeRunnable() { public void run() { IWorkbenchWindow windows[] = getWorkbenchWindows(); @@ -1052,13 +1128,14 @@ public final class Workbench extends EventManager implements IWorkbench { List<EditorReference> referencesToClose = new ArrayList<EditorReference>(); for (EditorReference reference : editorReferences) { IEditorPart editor = reference.getEditor(false); - if (editor != null && !reference.persist()) { + if (editor != null && !reference.persist() && shutdown) { referencesToClose.add(reference); } } - - for (EditorReference reference : referencesToClose) { - ((WorkbenchPage) pages[j]).closeEditor(reference); + if (shutdown) { + for (EditorReference reference : referencesToClose) { + ((WorkbenchPage) pages[j]).closeEditor(reference); + } } } } @@ -1083,47 +1160,66 @@ public final class Workbench extends EventManager implements IWorkbench { } }); - if (!force && !isClosing) { - return false; + // now that we have updated the model, save it to workbench.xmi + // skip this during shutdown to be efficient since it is done again + // later + if (!shutdown) { + persistWorkbenchModel(); } + } - SafeRunner.run(new SafeRunnable(WorkbenchMessages.ErrorClosing) { - public void run() { - if (isClosing || force) { - // isClosing = windowManager.close(); - E4Util.unsupported("Need to close since no windowManager"); //$NON-NLS-1$ - MWindow selectedWindow = application.getSelectedElement(); - WorkbenchWindow selected = null; - for (IWorkbenchWindow window : getWorkbenchWindows()) { - WorkbenchWindow ww = (WorkbenchWindow) window; - if (ww.getModel() == selectedWindow) { - selected = ww; - } else { - ((WorkbenchWindow) window).close(false); - } - } - - if (selected != null) { - selected.close(false); - } + /** + * Copy the model, clean it up and write it out to workbench.xmi. Called as + * part of persist(false) during auto-save. + */ + private void persistWorkbenchModel() { + final MApplication appCopy = (MApplication) EcoreUtil.copy((EObject) application); + final IModelResourceHandler handler = e4Context.get(IModelResourceHandler.class); - windowsClosed = true; + Job cleanAndSaveJob = new Job("Workbench Auto-Save Background Job") { //$NON-NLS-1$ + @Override + protected IStatus run(IProgressMonitor monitor) { + final Resource res = handler.createResourceWithApp(appCopy); + cleanUpCopy(appCopy); + try { + res.save(null); + } catch (IOException e) { + // Just auto-save, we don't really care } + return Status.OK_STATUS; } - }); - if (!force && !isClosing) { - return false; + }; + cleanAndSaveJob.setPriority(Job.SHORT); + cleanAndSaveJob.setSystem(true); + cleanAndSaveJob.schedule(); + } + + private static void cleanUpCopy(MApplication appCopy) { + // clean up all trim bars that come from trim bar contributions + // the trim elements that need to be removed are stored in the trimBar. + for (MWindow window : appCopy.getChildren()) { + if (window instanceof MTrimmedWindow) { + MTrimmedWindow trimmedWindow = (MTrimmedWindow) window; + // clean up the main menu to avoid duplicate menu items + window.setMainMenu(null); + // clean up trim bars created through contributions + // to avoid duplicate toolbars + for (MTrimBar trimBar : trimmedWindow.getTrimBars()) { + cleanUpTrimBar(trimBar); + } + } } + appCopy.getMenuContributions().clear(); + appCopy.getToolBarContributions().clear(); + appCopy.getTrimContributions().clear(); + } - shutdown(); - - IPresentationEngine engine = application.getContext().get(IPresentationEngine.class); - engine.stop(); - //System.err.println("stop()"); //$NON-NLS-1$ - - runEventLoop = false; - return true; + private static void cleanUpTrimBar(MTrimBar element) { + for (MTrimElement child : element.getPendingCleanup()) { + element.getChildren().remove(child); + } + element.getPendingCleanup().clear(); } /* @@ -2577,6 +2673,26 @@ UIEvents.Context.TOPIC_CONTEXT, } }; e4Context.set(PartRenderingEngine.EARLY_STARTUP_HOOK, earlyStartup); + // start workspace auto-save + final int millisecondInterval = getAutoSaveJobTime(); + if (millisecondInterval > 0) { + autoSaveJob = new WorkbenchJob("Workbench Auto-Save Job") { //$NON-NLS-1$ + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + final int nextDelay = getAutoSaveJobTime(); + persist(false); + monitor.done(); + // repeat + if (nextDelay > 0) { + this.schedule(nextDelay); + } + return Status.OK_STATUS; + } + }; + autoSaveJob.setSystem(true); + autoSaveJob.schedule(millisecondInterval); + } + // WWinPluginAction.refreshActionList(); display.asyncExec(new Runnable() { @@ -2612,6 +2728,13 @@ UIEvents.Context.TOPIC_CONTEXT, return returnCode; } + private int getAutoSaveJobTime() { + final int minuteSaveInterval = getPreferenceStore().getInt( + IPreferenceConstants.WORKBENCH_SAVE_INTERVAL); + final int millisecondInterval = minuteSaveInterval * 60 * 1000; + return millisecondInterval; + } + /* diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java index 31c0a02a32d..6a676d2e697 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2012 IBM Corporation and others. + * Copyright (c) 2005, 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 @@ -9,6 +9,9 @@ * IBM - Initial API and implementation * Sebastian Davids - bug 128529 * Semion Chichelnitsky (semion@il.ibm.com) - bug 278064 + * Tristan Hume - <trishume@gmail.com> - + * Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting + * Implemented workbench auto-save to correctly restore state in case of crash. *******************************************************************************/ package org.eclipse.ui.internal; @@ -806,6 +809,8 @@ public class WorkbenchMessages extends NLS { public static String WorkbenchPreference_reuseEditorsThresholdError; public static String WorkbenchPreference_recentFiles; public static String WorkbenchPreference_recentFilesError; + public static String WorkbenchPreference_workbenchSaveInterval; + public static String WorkbenchPreference_workbenchSaveIntervalError; public static String WorkbenchEditorsAction_label; public static String WorkbookEditorsAction_label; diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPreferenceInitializer.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPreferenceInitializer.java index e0c75215ec1..031b4f8ef09 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPreferenceInitializer.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchPreferenceInitializer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 IBM Corporation and others. + * Copyright (c) 2000, 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 @@ -8,6 +8,9 @@ * Contributors: * IBM Corporation - initial API and implementation * Semion Chichelnitsky (semion@il.ibm.com) - bug 278064 + * Tristan Hume - <trishume@gmail.com> - + * Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting + * Implemented workbench auto-save to correctly restore state in case of crash. *******************************************************************************/ package org.eclipse.ui.internal; @@ -58,9 +61,13 @@ public class WorkbenchPreferenceInitializer extends node.putBoolean(IPreferenceConstants.OPEN_AFTER_DELAY, false); node.putInt(IPreferenceConstants.RECENT_FILES, 4); - + // FIXME this does not actually set the default since it is the wrong + // node. It works because the default-default is false. node.putBoolean(IWorkbenchPreferenceConstants.DISABLE_OPEN_EDITOR_IN_PLACE, false); + // 5 minute workbench save interval + node.putInt(IPreferenceConstants.WORKBENCH_SAVE_INTERVAL, 5); + node.putBoolean(IPreferenceConstants.USE_IPERSISTABLE_EDITORS, true); node.putBoolean(IPreferenceConstants.COOLBAR_VISIBLE, true); @@ -95,6 +102,8 @@ public class WorkbenchPreferenceInitializer extends node.putBoolean("DISABLE_DIALOG_FONT", false); //$NON-NLS-1$ // Heap status preferences + // FIXME this does not actually set the default since it is the wrong + // node. It works because the default-default is false. node.putBoolean(IWorkbenchPreferenceConstants.SHOW_MEMORY_MONITOR, false); node.putInt(IHeapStatusConstants.PREF_UPDATE_INTERVAL, 500); node.putBoolean(IHeapStatusConstants.PREF_SHOW_MAX, false); diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/WorkbenchPreferencePage.java b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/WorkbenchPreferencePage.java index b0f484527ac..e2bdb3516ef 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/WorkbenchPreferencePage.java +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/dialogs/WorkbenchPreferencePage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 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 @@ -7,13 +7,23 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Tristan Hume - <trishume@gmail.com> - + * Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting + * Implemented workbench auto-save to correctly restore state in case of crash. *******************************************************************************/ package org.eclipse.ui.internal.dialogs; + import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.preference.FieldEditor; import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.IntegerFieldEditor; import org.eclipse.jface.preference.PreferencePage; +import org.eclipse.jface.preference.StringFieldEditor; +import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.OpenStrategy; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; @@ -55,6 +65,8 @@ public class WorkbenchPreferencePage extends PreferencePage implements private Button showUserDialogButton; + private IntegerFieldEditor saveInterval; + private boolean openOnSingleClick; private boolean selectOnHover; @@ -63,6 +75,8 @@ public class WorkbenchPreferencePage extends PreferencePage implements private Button showHeapStatusButton; + protected static int MAX_SAVE_INTERVAL = 9999; + /* * (non-Javadoc) * @@ -77,7 +91,7 @@ public class WorkbenchPreferencePage extends PreferencePage implements Composite composite = createComposite(parent); - createButtons(composite); + createSettings(composite); createSpace(composite); createOpenModeGroup(composite); @@ -91,10 +105,11 @@ public class WorkbenchPreferencePage extends PreferencePage implements * Create the buttons at the top of the preference page. * @param composite */ - protected void createButtons(Composite composite) { + protected void createSettings(Composite composite) { createShowUserDialogPref(composite); createStickyCyclePref(composite); createHeapStatusPref(composite); + createSaveIntervalGroup(composite); } /** @@ -151,6 +166,51 @@ public class WorkbenchPreferencePage extends PreferencePage implements IPreferenceConstants.STICKY_CYCLE)); } + /** + * Create a composite that contains entry fields specifying save interval + * preference. + * + * @param composite + * the Composite the group is created in. + */ + private void createSaveIntervalGroup(Composite composite) { + Composite groupComposite = new Composite(composite, SWT.LEFT); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + groupComposite.setLayout(layout); + GridData gd = new GridData(); + gd.horizontalAlignment = GridData.FILL; + gd.grabExcessHorizontalSpace = true; + groupComposite.setLayoutData(gd); + + saveInterval = new IntegerFieldEditor(IPreferenceConstants.WORKBENCH_SAVE_INTERVAL, + WorkbenchMessages.WorkbenchPreference_workbenchSaveInterval, groupComposite); + + // @issue we should drop our preference constant and let clients use + // core's pref. ours is not up-to-date anyway if someone changes this + // interval directly thru core api. + saveInterval.setPreferenceStore(getPreferenceStore()); + saveInterval.setPage(this); + saveInterval.setTextLimit(Integer.toString(MAX_SAVE_INTERVAL).length()); + saveInterval.setErrorMessage(NLS.bind( + WorkbenchMessages.WorkbenchPreference_workbenchSaveIntervalError, new Integer( + MAX_SAVE_INTERVAL))); + saveInterval.setValidateStrategy(StringFieldEditor.VALIDATE_ON_KEY_STROKE); + saveInterval.setValidRange(0, MAX_SAVE_INTERVAL); + + saveInterval.load(); + + saveInterval.setPropertyChangeListener(new IPropertyChangeListener() { + + public void propertyChange(PropertyChangeEvent event) { + if (event.getProperty().equals(FieldEditor.IS_VALID)) { + setValid(saveInterval.isValid()); + } + } + }); + + } + protected void createOpenModeGroup(Composite composite) { Font font = composite.getFont(); @@ -317,6 +377,7 @@ public class WorkbenchPreferencePage extends PreferencePage implements */ protected void performDefaults() { IPreferenceStore store = getPreferenceStore(); + saveInterval.loadDefault(); stickyCycleButton.setSelection(store .getBoolean(IPreferenceConstants.STICKY_CYCLE)); openOnSingleClick = store @@ -356,6 +417,7 @@ public class WorkbenchPreferencePage extends PreferencePage implements store.setValue(IPreferenceConstants.OPEN_AFTER_DELAY, openAfterDelay); store.setValue(IPreferenceConstants.RUN_IN_BACKGROUND, showUserDialogButton.getSelection()); + store.setValue(IPreferenceConstants.WORKBENCH_SAVE_INTERVAL, saveInterval.getIntValue()); PrefUtil.getAPIPreferenceStore().setValue(IWorkbenchPreferenceConstants.SHOW_MEMORY_MONITOR, showHeapStatusButton.getSelection()); updateHeapStatus(showHeapStatusButton.getSelection()); diff --git a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/messages.properties b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/messages.properties index ae8346d9b14..b1fc37c4dc9 100644 --- a/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/messages.properties +++ b/bundles/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2000, 2012 IBM Corporation and others. +# Copyright (c) 2000, 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 @@ -12,6 +12,9 @@ # - Fix for Bug 138034 [Preferences] Label decorations page - extra space # - Fix for Bug 128529 # Semion Chichelnitsky (semion@il.ibm.com) - bug 278064 +# Tristan Hume - <trishume@gmail.com> - +# Fix for Bug 2369 [Workbench] Would like to be able to save workspace without exiting +# Implemented workbench auto-save to correctly restore state in case of crash. ############################################################################### # package: org.eclipse.ui @@ -771,6 +774,8 @@ WorkbenchPreference_reuseEditorsThreshold=Number of opened editors before closi& WorkbenchPreference_reuseEditorsThresholdError=The number of opened editors should be more than 0. WorkbenchPreference_recentFiles=Size of &recently opened files list: WorkbenchPreference_recentFilesError=The size of the recently opened files list should be between 0 and {0}. +WorkbenchPreference_workbenchSaveInterval=Workbench Save Interval +WorkbenchPreference_workbenchSaveIntervalError=The workbench save interval should be an integer between 0 and {0}. WorkbenchEditorsAction_label=S&witch to Editor... WorkbookEditorsAction_label=&Quick Switch Editor |
