Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 55378 Details for
Bug 154122
[EditorMgmt] Enable background saving of editors
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
about to release this patch...
patch-154122.txt (text/plain), 53.70 KB, created by
Boris Bokowski
on 2006-12-10 23:36:44 EST
(
hide
)
Description:
about to release this patch...
Filename:
MIME Type:
Creator:
Boris Bokowski
Created:
2006-12-10 23:36:44 EST
Size:
53.70 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.ui.tests >Index: plugin.xml >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.ui.tests/plugin.xml,v >retrieving revision 1.213 >diff -u -r1.213 plugin.xml >--- plugin.xml 8 Dec 2006 15:09:18 -0000 1.213 >+++ plugin.xml 11 Dec 2006 04:34:11 -0000 >@@ -663,6 +663,14 @@ > icon="icons/mockeditorpart1.gif" > id="org.eclipse.ui.tests.multipageeditor.MultiVariablePageEditor" > name="Multi Variable Page Editor"/> >+ <editor >+ class="org.eclipse.ui.tests.manual.TestBackgroundSaveEditor" >+ default="false" >+ extensions="background" >+ icon="icons/binary_co.gif" >+ id="org.eclipse.ui.tests.manual.TestBackgroundSaveEditor" >+ name="TestBackgroundSaveEditor"> >+ </editor> > </extension> > <extension > point="org.eclipse.ui.actionSets"> >Index: META-INF/MANIFEST.MF >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.ui.tests/META-INF/MANIFEST.MF,v >retrieving revision 1.6 >diff -u -r1.6 MANIFEST.MF >--- META-INF/MANIFEST.MF 4 Dec 2006 20:56:28 -0000 1.6 >+++ META-INF/MANIFEST.MF 11 Dec 2006 04:34:11 -0000 >@@ -21,7 +21,10 @@ > org.eclipse.test.performance, > org.eclipse.core.tests.harness, > org.eclipse.ui.tests.harness, >- org.eclipse.core.filesystem >+ org.eclipse.core.filesystem, >+ org.eclipse.core.databinding, >+ org.eclipse.core.databinding.beans, >+ org.eclipse.jface.databinding > Eclipse-AutoStart: true > Plugin-Class: org.eclipse.ui.tests.TestPlugin > Export-Package: org.eclipse.ui.tests.menus >Index: Eclipse UI Tests/org/eclipse/ui/tests/manual/TestBackgroundSaveEditor.java >=================================================================== >RCS file: Eclipse UI Tests/org/eclipse/ui/tests/manual/TestBackgroundSaveEditor.java >diff -N Eclipse UI Tests/org/eclipse/ui/tests/manual/TestBackgroundSaveEditor.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ Eclipse UI Tests/org/eclipse/ui/tests/manual/TestBackgroundSaveEditor.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,496 @@ >+/******************************************************************************* >+ * Copyright (c) 2006 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.tests.manual; >+ >+import java.beans.PropertyChangeListener; >+import java.beans.PropertyChangeSupport; >+ >+import org.eclipse.core.databinding.DataBindingContext; >+import org.eclipse.core.databinding.beans.BeansObservables; >+import org.eclipse.core.databinding.observable.Realm; >+import org.eclipse.core.databinding.observable.value.IObservableValue; >+import org.eclipse.core.runtime.Assert; >+import org.eclipse.core.runtime.CoreException; >+import org.eclipse.core.runtime.IProgressMonitor; >+import org.eclipse.core.runtime.IStatus; >+import org.eclipse.core.runtime.Status; >+import org.eclipse.core.runtime.SubMonitor; >+import org.eclipse.jface.databinding.swt.SWTObservables; >+import org.eclipse.jface.dialogs.MessageDialog; >+import org.eclipse.jface.layout.GridDataFactory; >+import org.eclipse.jface.layout.GridLayoutFactory; >+import org.eclipse.jface.resource.ImageDescriptor; >+import org.eclipse.jface.window.IShellProvider; >+import org.eclipse.swt.SWT; >+import org.eclipse.swt.events.DisposeEvent; >+import org.eclipse.swt.events.DisposeListener; >+import org.eclipse.swt.widgets.Button; >+import org.eclipse.swt.widgets.Composite; >+import org.eclipse.swt.widgets.Group; >+import org.eclipse.swt.widgets.Label; >+import org.eclipse.swt.widgets.Text; >+import org.eclipse.ui.IEditorInput; >+import org.eclipse.ui.IEditorSite; >+import org.eclipse.ui.IFileEditorInput; >+import org.eclipse.ui.ISaveablePart; >+import org.eclipse.ui.ISaveablesSource; >+import org.eclipse.ui.PartInitException; >+import org.eclipse.ui.PlatformUI; >+import org.eclipse.ui.Saveable; >+import org.eclipse.ui.internal.WorkbenchMessages; >+import org.eclipse.ui.internal.WorkbenchPlugin; >+import org.eclipse.ui.internal.progress.WorkbenchSiteProgressService; >+import org.eclipse.ui.part.EditorPart; >+import org.eclipse.ui.progress.IJobRunnable; >+import org.eclipse.ui.progress.IWorkbenchSiteProgressService; >+ >+/** >+ * @since 3.3 >+ * >+ */ >+public class TestBackgroundSaveEditor extends EditorPart implements >+ ISaveablesSource { >+ >+ public class MySaveable extends Saveable { >+ >+ PropertyChangeSupport changeSupport = new PropertyChangeSupport(this); >+ >+ private boolean dirty; >+ >+ public boolean supportsBackgroundSave() { >+ return true; >+ } >+ >+ public void doSave(IProgressMonitor monitor) throws CoreException { >+ SubMonitor subMonitor = SubMonitor.convert(monitor, 2); >+ IJobRunnable runnable = doSave(subMonitor.newChild(1), getSite()); >+ if (runnable!=null) { >+ runnable.run(subMonitor.newChild(1)); >+ } >+ monitor.done(); >+ } >+ >+ public IJobRunnable doSave(IProgressMonitor monitor, >+ IShellProvider shellProvider) throws CoreException { >+ monitor.beginTask("Saving in the foreground", >+ data.foregroundSaveTime); >+ data.setOutput(""); >+ for (int i = 0; i < data.foregroundSaveTime; i++) { >+ try { >+ Thread.sleep(1000); >+ } catch (InterruptedException e) { >+ Thread.currentThread().interrupt(); >+ } >+ data.setOutput(data.getInput().substring(0, >+ Math.min(i, data.getInput().length()))); >+ monitor.worked(1); >+ } >+ if (data.throwExceptionInForeground) { >+ throw new CoreException(new Status(IStatus.ERROR, >+ "org.eclipse.ui.tests", >+ "Saving in the foreground failed")); >+ } >+ monitor.done(); >+ if (!data.saveInBackground) { >+ data.setOutput(data.getInput()); >+ setDirty(false); >+ return null; >+ } >+ WorkbenchSiteProgressService progressService = (WorkbenchSiteProgressService) getSite() >+ .getAdapter(IWorkbenchSiteProgressService.class); >+ IJobRunnable result = new IJobRunnable() { >+ public IStatus run(IProgressMonitor monitor) { >+ monitor.beginTask("Saving in the background", >+ data.backgroundSaveTime); >+ for (int i = 0; i < data.backgroundSaveTime; i++) { >+ try { >+ Thread.sleep(1000); >+ } catch (InterruptedException e) { >+ Thread.currentThread().interrupt(); >+ } >+ data.setOutput(data.getInput().substring( >+ 0, >+ Math.min(i + data.foregroundSaveTime, data >+ .getInput().length()))); >+ monitor.worked(1); >+ } >+ if (data.throwExceptionInBackground) { >+ return new Status(IStatus.ERROR, >+ "org.eclipse.ui.tests", >+ "Saving in the background failed"); >+ } >+ data.setOutput(data.getInput()); >+ setDirty(false); >+ monitor.done(); >+ return Status.OK_STATUS; >+ } >+ }; >+ return result; >+ } >+ >+ public boolean equals(Object object) { >+ return this == object; >+ } >+ >+ public ImageDescriptor getImageDescriptor() { >+ return input.getImageDescriptor(); >+ } >+ >+ public String getName() { >+ return input.getName(); >+ } >+ >+ public String getToolTipText() { >+ return input.getToolTipText(); >+ } >+ >+ public int hashCode() { >+ return System.identityHashCode(this); >+ } >+ >+ public boolean isDirty() { >+ return dirty; >+ } >+ >+ public void setDirty(boolean dirty) { >+ firePropertyChange("dirty", new Boolean(this.dirty), new Boolean( >+ this.dirty = dirty)); >+ getSite().getShell().getDisplay().syncExec(new Runnable(){ >+ public void run() { >+ TestBackgroundSaveEditor.this >+ .firePropertyChange(ISaveablePart.PROP_DIRTY); >+ }}); >+ } >+ >+ public void addPropertyChangeListener(String propertyName, >+ PropertyChangeListener listener) { >+ changeSupport.addPropertyChangeListener(propertyName, listener); >+ } >+ >+ void firePropertyChange(String propertyName, Object oldValue, >+ Object newValue) { >+ changeSupport.firePropertyChange(propertyName, oldValue, newValue); >+ } >+ >+ public void removePropertyChangeListener(String propertyName, >+ PropertyChangeListener listener) { >+ changeSupport.removePropertyChangeListener(propertyName, listener); >+ } >+ } >+ >+ private MySaveable mySaveable; >+ private Text inputText; >+ private IEditorInput input; >+ private Composite myComposite; >+ >+ public TestBackgroundSaveEditor() { >+ mySaveable = new MySaveable(); >+ } >+ >+ public void createPartControl(Composite parent) { >+ myComposite = parent; >+ Realm realm = SWTObservables.getRealm(parent.getDisplay()); >+ final DataBindingContext dbc = new DataBindingContext(realm); >+ parent.addDisposeListener(new DisposeListener() { >+ public void widgetDisposed(DisposeEvent e) { >+ dbc.dispose(); >+ } >+ }); >+ >+ final IObservableValue inputObservable = BeansObservables.observeValue( >+ realm, data, "input"); >+ final IObservableValue outputObservable = BeansObservables >+ .observeValue(realm, data, "output"); >+ >+ createInputGroup(parent, dbc, inputObservable); >+ createOptionsGroup(parent, realm, dbc, inputObservable, >+ outputObservable); >+ createOutputGroup(parent, dbc, outputObservable); >+ >+ GridLayoutFactory.swtDefaults().numColumns(3).equalWidth(true) >+ .generateLayout(parent); >+ } >+ >+ private void createOutputGroup(Composite parent, >+ final DataBindingContext dbc, >+ final IObservableValue outputObservable) { >+ Group outputGroup = new Group(parent, SWT.NONE); >+ outputGroup.setText("Output"); >+ Text outputText = new Text(outputGroup, SWT.BORDER | SWT.READ_ONLY >+ | SWT.MULTI); >+ GridDataFactory.fillDefaults().grab(true, true).applyTo(outputText); >+ dbc.bindValue(SWTObservables.observeText(outputText, SWT.NONE), >+ outputObservable, null); >+ GridLayoutFactory.swtDefaults().generateLayout(outputGroup); >+ } >+ >+ private void createOptionsGroup(Composite parent, Realm realm, >+ final DataBindingContext dbc, >+ final IObservableValue inputObservable, >+ final IObservableValue outputObservable) { >+ Group optionsGroup = new Group(parent, SWT.NONE); >+ optionsGroup.setText("Options"); >+ >+ Button dirtyButton = new Button(optionsGroup, SWT.CHECK); >+ new Label(optionsGroup, SWT.NONE).setText("Editor is dirty"); >+ IObservableValue dirtyObservable = BeansObservables.observeValue(realm, >+ mySaveable, "dirty"); >+ dbc.bindValue(SWTObservables.observeSelection(dirtyButton), >+ dirtyObservable, null); >+ // IObservableValue inputAndOutputDiffer = new ComputedValue(realm) { >+ // protected Object calculate() { >+ // return new Boolean(!Util.equals(inputObservable.getValue(), >+ // outputObservable.getValue())); >+ // } >+ // }; >+ // dbc.bindValue(dirtyObservable, inputAndOutputDiffer, null); >+ >+ Button saveInBackgroundButton = new Button(optionsGroup, SWT.CHECK); >+ new Label(optionsGroup, SWT.NONE) >+ .setText("Do part of the save in the background"); >+ dbc.bindValue(SWTObservables.observeSelection(saveInBackgroundButton), >+ BeansObservables.observeValue(realm, data, "saveInBackground"), >+ null); >+ >+ Button foregroundExceptionButton = new Button(optionsGroup, SWT.CHECK); >+ new Label(optionsGroup, SWT.NONE) >+ .setText("Throw exception while saving in the foreground"); >+ dbc.bindValue(SWTObservables >+ .observeSelection(foregroundExceptionButton), BeansObservables >+ .observeValue(realm, data, "throwExceptionInForeground"), null); >+ >+ Button backgroundExceptionButton = new Button(optionsGroup, SWT.CHECK); >+ new Label(optionsGroup, SWT.NONE) >+ .setText("Throw exception while saving in the background"); >+ dbc.bindValue(SWTObservables >+ .observeSelection(backgroundExceptionButton), BeansObservables >+ .observeValue(realm, data, "throwExceptionInBackground"), null); >+ >+ new Label(optionsGroup, SWT.NONE).setText("Foreground save time:"); >+ Text optionsForegroundTime = new Text(optionsGroup, SWT.BORDER); >+ dbc.bindValue(SWTObservables.observeText(optionsForegroundTime, >+ SWT.Modify), BeansObservables.observeValue(realm, data, >+ "foregroundSaveTime"), null); >+ >+ new Label(optionsGroup, SWT.NONE).setText("Background save time:"); >+ Text optionsBackgroundTime = new Text(optionsGroup, SWT.BORDER); >+ dbc.bindValue(SWTObservables.observeText(optionsBackgroundTime, >+ SWT.Modify), BeansObservables.observeValue(realm, data, >+ "backgroundSaveTime"), null); >+ >+ GridLayoutFactory.swtDefaults().numColumns(2).generateLayout( >+ optionsGroup); >+ } >+ >+ private void createInputGroup(Composite parent, >+ final DataBindingContext dbc, final IObservableValue inputObservable) { >+ Group inputGroup = new Group(parent, SWT.NONE); >+ inputGroup.setText("Input"); >+ >+ inputText = new Text(inputGroup, SWT.BORDER | SWT.MULTI); >+ dbc.bindValue(SWTObservables.observeText(inputText, SWT.Modify), >+ inputObservable, null); >+ >+ GridLayoutFactory.swtDefaults().generateLayout(inputGroup); >+ } >+ >+ public void doSave(IProgressMonitor monitor) { >+ try { >+ mySaveable.doSave(monitor); >+ } catch (CoreException e) { >+ String title = "Save failed"; >+ WorkbenchPlugin.log(title, new Status(IStatus.WARNING, >+ PlatformUI.PLUGIN_ID, 0, title, e)); >+ MessageDialog.openError(getSite().getShell(), >+ WorkbenchMessages.Error, title + ':' + e.getMessage()); >+ } >+ } >+ >+ public void doSaveAs() { >+ Assert.isTrue(false, "Should not be called"); >+ } >+ >+ public void init(IEditorSite site, IEditorInput input) >+ throws PartInitException { >+ if (!(input instanceof IFileEditorInput)) >+ throw new PartInitException( >+ "Invalid Input: Must be IFileEditorInput"); >+ setSite(site); >+ setInput(input); >+ this.input = input; >+ } >+ >+ public boolean isDirty() { >+ return mySaveable.isDirty(); >+ } >+ >+ public boolean isSaveAsAllowed() { >+ return false; >+ } >+ >+ public void setFocus() { >+ inputText.setFocus(); >+ } >+ >+ public static class Data { >+ PropertyChangeSupport changeSupport = new PropertyChangeSupport(this); >+ public String input; >+ public String output; >+ public String buffer; >+ public boolean saveInBackground; >+ public boolean throwExceptionInForeground; >+ public boolean throwExceptionInBackground; >+ public int foregroundSaveTime; >+ public int backgroundSaveTime; >+ >+ public String getOutput() { >+ return output; >+ } >+ >+ public void setOutput(String output) { >+ firePropertyChange("output", this.output, this.output = output); >+ } >+ >+ public void addPropertyChangeListener(String propertyName, >+ PropertyChangeListener listener) { >+ changeSupport.addPropertyChangeListener(propertyName, listener); >+ } >+ >+ void firePropertyChange(String propertyName, Object oldValue, >+ Object newValue) { >+ changeSupport.firePropertyChange(propertyName, oldValue, newValue); >+ } >+ >+ public void removePropertyChangeListener(String propertyName, >+ PropertyChangeListener listener) { >+ changeSupport.removePropertyChangeListener(propertyName, listener); >+ } >+ >+ /** >+ * @return Returns the input. >+ */ >+ public String getInput() { >+ return input; >+ } >+ >+ /** >+ * @param input >+ * The input to set. >+ */ >+ public void setInput(String input) { >+ this.input = input; >+ } >+ >+ /** >+ * @return Returns the buffer. >+ */ >+ public String getBuffer() { >+ return buffer; >+ } >+ >+ /** >+ * @param buffer >+ * The buffer to set. >+ */ >+ public void setBuffer(String buffer) { >+ this.buffer = buffer; >+ } >+ >+ /** >+ * @return Returns the saveInBackground. >+ */ >+ public boolean isSaveInBackground() { >+ return saveInBackground; >+ } >+ >+ /** >+ * @param saveInBackground >+ * The saveInBackground to set. >+ */ >+ public void setSaveInBackground(boolean saveInBackground) { >+ this.saveInBackground = saveInBackground; >+ } >+ >+ /** >+ * @return Returns the throwExceptionInForeground. >+ */ >+ public boolean isThrowExceptionInForeground() { >+ return throwExceptionInForeground; >+ } >+ >+ /** >+ * @param throwExceptionInForeground >+ * The throwExceptionInForeground to set. >+ */ >+ public void setThrowExceptionInForeground( >+ boolean throwExceptionInForeground) { >+ this.throwExceptionInForeground = throwExceptionInForeground; >+ } >+ >+ /** >+ * @return Returns the throwExceptionInBackground. >+ */ >+ public boolean isThrowExceptionInBackground() { >+ return throwExceptionInBackground; >+ } >+ >+ /** >+ * @param throwExceptionInBackground >+ * The throwExceptionInBackground to set. >+ */ >+ public void setThrowExceptionInBackground( >+ boolean throwExceptionInBackground) { >+ this.throwExceptionInBackground = throwExceptionInBackground; >+ } >+ >+ /** >+ * @return Returns the foregroundSaveTime. >+ */ >+ public int getForegroundSaveTime() { >+ return foregroundSaveTime; >+ } >+ >+ /** >+ * @param foregroundSaveTime >+ * The foregroundSaveTime to set. >+ */ >+ public void setForegroundSaveTime(int foregroundSaveTime) { >+ this.foregroundSaveTime = foregroundSaveTime; >+ } >+ >+ /** >+ * @return Returns the backgroundSaveTime. >+ */ >+ public int getBackgroundSaveTime() { >+ return backgroundSaveTime; >+ } >+ >+ /** >+ * @param backgroundSaveTime >+ * The backgroundSaveTime to set. >+ */ >+ public void setBackgroundSaveTime(int backgroundSaveTime) { >+ this.backgroundSaveTime = backgroundSaveTime; >+ } >+ } >+ >+ private Data data = new Data(); >+ >+ public Saveable[] getActiveSaveables() { >+ return new Saveable[] { mySaveable }; >+ } >+ >+ public Saveable[] getSaveables() { >+ return new Saveable[] { mySaveable }; >+ } >+ >+} >#P org.eclipse.ui.workbench >Index: Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java,v >retrieving revision 1.361 >diff -u -r1.361 WorkbenchWindow.java >--- Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java 10 Dec 2006 22:11:34 -0000 1.361 >+++ Eclipse UI/org/eclipse/ui/internal/WorkbenchWindow.java 11 Dec 2006 04:34:20 -0000 >@@ -2859,6 +2859,8 @@ > > private ListenerList actionSetListeners = null; > >+ private ListenerList backgroundSaveListeners = new ListenerList(ListenerList.IDENTITY); >+ > private final void fireActionSetsChanged() { > if (actionSetListeners != null) { > final Object[] listeners = actionSetListeners.getListeners(); >@@ -3676,4 +3678,20 @@ > setPerspectiveBarVisible(!perspectivebarVisible); > getShell().layout(); > } >+ >+ /*package*/ void addBackgroundSaveListener(IBackgroundSaveListener listener) { >+ backgroundSaveListeners.add(listener); >+ } >+ >+ /*package*/ void fireBackgroundSaveStarted() { >+ Object[] listeners = backgroundSaveListeners.getListeners(); >+ for (int i = 0; i < listeners.length; i++) { >+ IBackgroundSaveListener listener = (IBackgroundSaveListener) listeners[i]; >+ listener.handleBackgroundSaveStarted(); >+ } >+ } >+ >+ /*package*/ void removeBackgroundSaveListener(IBackgroundSaveListener listener) { >+ backgroundSaveListeners.remove(listener); >+ } > } >Index: Eclipse UI/org/eclipse/ui/internal/SaveAction.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/SaveAction.java,v >retrieving revision 1.23 >diff -u -r1.23 SaveAction.java >--- Eclipse UI/org/eclipse/ui/internal/SaveAction.java 8 May 2006 20:55:36 -0000 1.23 >+++ Eclipse UI/org/eclipse/ui/internal/SaveAction.java 11 Dec 2006 04:34:15 -0000 >@@ -19,7 +19,7 @@ > /** > * Workbench common <code>Save</code> action. > */ >-public class SaveAction extends BaseSaveAction { >+public class SaveAction extends BaseSaveAction implements IBackgroundSaveListener { > > /** > * Create an instance of this class >@@ -38,6 +38,12 @@ > setDisabledImageDescriptor(WorkbenchImages > .getImageDescriptor(IWorkbenchGraphicConstants.IMG_ETOOL_SAVE_EDIT_DISABLED)); > setActionDefinitionId("org.eclipse.ui.file.save"); //$NON-NLS-1$ >+ ((WorkbenchWindow)window).addBackgroundSaveListener(this); >+ } >+ >+ public void dispose() { >+ super.dispose(); >+ ((WorkbenchWindow)getWorkbenchWindow()).removeBackgroundSaveListener(this); > } > > /* (non-Javadoc) >@@ -88,4 +94,8 @@ > } > setEnabled(saveable != null && saveable.isDirty()); > } >+ >+ public void handleBackgroundSaveStarted() { >+ updateState(); >+ } > } >Index: Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java,v >retrieving revision 1.75 >diff -u -r1.75 WorkbenchMessages.java >--- Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java 24 Nov 2006 16:41:35 -0000 1.75 >+++ Eclipse UI/org/eclipse/ui/internal/WorkbenchMessages.java 11 Dec 2006 04:34:17 -0000 >@@ -521,6 +521,7 @@ > public static String EditorManager_bad_element_factory; > public static String EditorManager_create_element_returned_null; > public static String EditorManager_wrong_createElement_result; >+ public static String EditorManager_backgroundSaveJobName; > > public static String EditorPane_pinEditor; > >Index: Eclipse UI/org/eclipse/ui/internal/messages.properties >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/messages.properties,v >retrieving revision 1.333 >diff -u -r1.333 messages.properties >--- Eclipse UI/org/eclipse/ui/internal/messages.properties 24 Nov 2006 16:41:35 -0000 1.333 >+++ Eclipse UI/org/eclipse/ui/internal/messages.properties 11 Dec 2006 04:34:20 -0000 >@@ -517,6 +517,7 @@ > EditorManager_invalid_editor_descriptor=Invalid editor descriptor for id {0} > EditorManager_problemsSavingEditors=Problems occurred saving editors. > EditorManager_unableToSaveEditor=Unable to save editor: {0}. >+EditorManager_backgroundSaveJobName=Saving {0} > > EditorPane_pinEditor=&Pin Editor > >Index: Eclipse UI/org/eclipse/ui/internal/PartPane.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/PartPane.java,v >retrieving revision 1.85 >diff -u -r1.85 PartPane.java >--- Eclipse UI/org/eclipse/ui/internal/PartPane.java 8 May 2006 20:55:35 -0000 1.85 >+++ Eclipse UI/org/eclipse/ui/internal/PartPane.java 11 Dec 2006 04:34:15 -0000 >@@ -37,6 +37,7 @@ > import org.eclipse.ui.IWorkbenchPartReference; > import org.eclipse.ui.internal.dnd.SwtUtil; > import org.eclipse.ui.part.MultiEditor; >+import org.eclipse.ui.presentations.IPresentablePart; > > /** > * Provides the common behavior for both views >@@ -94,6 +95,8 @@ > > }; > >+ private boolean busy; >+ > public static class Sashes { > public Sash left; > >@@ -491,7 +494,10 @@ > * Set the busy state of the pane. > */ > public void setBusy(boolean isBusy) { >- //Do nothing by default >+ if (isBusy != busy) { >+ busy = isBusy; >+ firePropertyChange(IPresentablePart.PROP_BUSY); >+ } > } > > /** >@@ -524,7 +530,7 @@ > } > > public boolean isBusy() { >- return false; >+ return busy; > } > > /** >Index: Eclipse UI/org/eclipse/ui/internal/ViewPane.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/ViewPane.java,v >retrieving revision 1.104 >diff -u -r1.104 ViewPane.java >--- Eclipse UI/org/eclipse/ui/internal/ViewPane.java 24 Feb 2006 18:36:11 -0000 1.104 >+++ Eclipse UI/org/eclipse/ui/internal/ViewPane.java 11 Dec 2006 04:34:16 -0000 >@@ -40,7 +40,6 @@ > * TODO: Delete ViewPane and EditorPane, and make PartPane non-abstract. > */ > public class ViewPane extends PartPane { >- private boolean busy = false; > > // create initially toolbarless bar manager so that actions may be added in the > // init method of the view. >@@ -548,25 +547,6 @@ > return toolbarManager.getItemCount() > 0; > } > >- /* >- * (non-Javadoc) >- * @see org.eclipse.ui.internal.PartPane#setBusy(boolean) >- */ >- public void setBusy(boolean isBusy) { >- if (isBusy != busy) { >- busy = isBusy; >- firePropertyChange(IPresentablePart.PROP_BUSY); >- } >- } >- >- /** >- * Return the busy state of the receiver. >- * @return boolean >- */ >- public boolean isBusy() { >- return busy; >- } >- > /* (non-Javadoc) > * @see org.eclipse.ui.internal.PartPane#showHighlight() > */ >Index: Eclipse UI/org/eclipse/ui/internal/SaveableHelper.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/SaveableHelper.java,v >retrieving revision 1.14 >diff -u -r1.14 SaveableHelper.java >--- Eclipse UI/org/eclipse/ui/internal/SaveableHelper.java 8 Nov 2006 15:13:29 -0000 1.14 >+++ Eclipse UI/org/eclipse/ui/internal/SaveableHelper.java 11 Dec 2006 04:34:15 -0000 >@@ -12,13 +12,21 @@ > > import java.lang.reflect.InvocationTargetException; > import java.util.ArrayList; >+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; > import org.eclipse.core.runtime.Status; >+import org.eclipse.core.runtime.SubMonitor; > import org.eclipse.core.runtime.SubProgressMonitor; >+import org.eclipse.core.runtime.jobs.IJobChangeEvent; >+import org.eclipse.core.runtime.jobs.ISchedulingRule; >+import org.eclipse.core.runtime.jobs.Job; >+import org.eclipse.core.runtime.jobs.JobChangeAdapter; > import org.eclipse.jface.dialogs.ErrorDialog; > import org.eclipse.jface.dialogs.IDialogConstants; > import org.eclipse.jface.dialogs.MessageDialog; >@@ -28,12 +36,15 @@ > import org.eclipse.osgi.util.NLS; > import org.eclipse.ui.ISaveablePart; > import org.eclipse.ui.ISaveablePart2; >+import org.eclipse.ui.ISaveablesLifecycleListener; > import org.eclipse.ui.ISaveablesSource; > import org.eclipse.ui.IWorkbenchPart; > import org.eclipse.ui.IWorkbenchWindow; > import org.eclipse.ui.PlatformUI; > import org.eclipse.ui.Saveable; > import org.eclipse.ui.internal.dialogs.EventLoopProgressMonitor; >+import org.eclipse.ui.progress.IJobRunnable; >+import org.eclipse.ui.progress.IWorkbenchSiteProgressService; > > /** > * Helper class for prompting to save dirty views or editors. >@@ -168,12 +179,8 @@ > monitor.worked(1); > continue; > } >- try { >- model.doSave(new SubProgressMonitor(monitorWrap, 1)); >- } >- catch (CoreException e) { >- ErrorDialog.openError(window.getShell(), WorkbenchMessages.Error, e.getMessage(), e.getStatus()); >- } >+ doSaveModel(model, new SubProgressMonitor(monitorWrap, 1), >+ (WorkbenchWindow) window, false); > if (monitor.isCanceled()) { > break; > } >@@ -288,11 +295,197 @@ > Saveable[] selectedModels = modelSource.getActiveSaveables(); > for (int i = 0; i < selectedModels.length; i++) { > Saveable model = selectedModels[i]; >- if (model.isDirty()) { >+ if (model.isDirty() && !((InternalSaveable)model).isSavingInBackground()) { > return true; > } > } > return false; > } >- >+ >+ /** >+ * @param model >+ * @param progressMonitor >+ * @param shellProvider >+ * @param closing >+ */ >+ public static void doSaveModel(final Saveable model, >+ IProgressMonitor progressMonitor, >+ final IShellProvider shellProvider, boolean closing) { >+ final ISchedulingRule schedulingRule = ((InternalSaveable) model) >+ .getSchedulingRule(); >+ boolean ruleTransferred = false; >+ try { >+ if (model.supportsBackgroundSave()) { >+ Job.getJobManager().beginRule(schedulingRule, null); >+ } else { >+ // To be safe for 3.3M4, don't lock if the saveable does not support background saves >+ ruleTransferred = true; >+ } >+ final IJobRunnable[] backgroundSaveRunnable = new IJobRunnable[1]; >+ try { >+ SubMonitor subMonitor = SubMonitor.convert(progressMonitor, 3); >+ backgroundSaveRunnable[0] = model.doSave( >+ subMonitor.newChild(2), shellProvider); >+ if (backgroundSaveRunnable[0] == null) { >+ return; >+ } >+ if (closing || !model.supportsBackgroundSave()) { >+ // for now, block on close by running the runnable in the UI >+ // thread >+ IStatus result = backgroundSaveRunnable[0].run(subMonitor >+ .newChild(1)); >+ if (!result.isOK()) { >+ ErrorDialog.openError(shellProvider.getShell(), >+ WorkbenchMessages.Error, result.getMessage(), >+ result); >+ progressMonitor.setCanceled(true); >+ } >+ return; >+ } >+ // we will need the associated parts (for disabling their UI) >+ ((InternalSaveable) model).setSavingInBackground(true); >+ SaveablesList saveablesList = (SaveablesList) PlatformUI >+ .getWorkbench().getService( >+ ISaveablesLifecycleListener.class); >+ final IWorkbenchPart[] parts = saveablesList >+ .getPartsForSaveable(model); >+ { >+ // about to start the job - notify the save actions, >+ // this is done through the workbench windows, which >+ // we can get from the parts... >+ Set wwindows = new HashSet(); >+ for (int i = 0; i < parts.length; i++) { >+ wwindows.add(parts[i].getSite().getWorkbenchWindow()); >+ } >+ for (Iterator it = wwindows.iterator(); it.hasNext();) { >+ WorkbenchWindow wwin = (WorkbenchWindow) it.next(); >+ wwin.fireBackgroundSaveStarted(); >+ } >+ } >+ // for the job family, we use the model object because based on >+ // the family we can display the busy state with an animated tab >+ // (see the calls to showBusyForFamily() below). >+ // As a "lock", we use a scheduling rule obtained from the model. >+ // This lock is already held by the UI thread at this time. We >+ // will transfer it to the job. This lock is necessary so that >+ // saves or close-on-dirty that happen later, but still concurrent >+ // with the background save, are blocked until the background save >+ // is finished. >+ Job saveJob = new Job(NLS.bind( >+ WorkbenchMessages.EditorManager_backgroundSaveJobName, >+ model.getName())) { >+ public boolean belongsTo(Object family) { >+ return family.equals(model); >+ } >+ >+ protected IStatus run(IProgressMonitor monitor) { >+ try { >+ Job.getJobManager().beginRule(schedulingRule, null); >+ return backgroundSaveRunnable[0].run(monitor); >+ } finally { >+ Job.getJobManager().endRule(schedulingRule); >+ Job.getJobManager().endRule(schedulingRule); >+ } >+ } >+ }; >+ // this will cause the parts tabs to show the ongoing background operation >+ for (int i = 0; i < parts.length; i++) { >+ IWorkbenchPart workbenchPart = parts[i]; >+ IWorkbenchSiteProgressService progressService = (IWorkbenchSiteProgressService) workbenchPart >+ .getSite().getAdapter( >+ IWorkbenchSiteProgressService.class); >+ progressService.showBusyForFamily(model); >+ } >+ model.disableUI(parts, closing); >+ // Add a listener for enabling the UI after the save job has >+ // finished, and for displaying an error dialog if >+ // necessary. We also use this to notify the UI thread that >+ // the job has started. This complicated dance is necessary >+ // to transfer the schedulingRule to the new job because we >+ // can only do that once we know the thread to transfer the >+ // rule to. >+ final Boolean[] latch = { Boolean.FALSE }; >+ saveJob.addJobChangeListener(new JobChangeAdapter() { >+ public void done(final IJobChangeEvent event) { >+ shellProvider.getShell().getDisplay().asyncExec( >+ new Runnable() { >+ public void run() { >+ ((InternalSaveable) model) >+ .setSavingInBackground(false); >+ model.enableUI(parts); >+ IStatus result = event.getResult(); >+ if (!result.isOK()) { >+ ErrorDialog >+ .openError( >+ shellProvider >+ .getShell(), >+ WorkbenchMessages.Error, >+ result.getMessage(), >+ result); >+ } >+ } >+ }); >+ } >+ >+ public void running(IJobChangeEvent event) { >+ synchronized (latch) { >+ latch[0] = Boolean.TRUE; >+ latch.notifyAll(); >+ } >+ } >+ }); >+ // Finally, we are ready to schedule the job. >+ // The job will block on the "beginRule" call since >+ // we haven't transferred the rule to it yet. We can >+ // only do that >+ saveJob.schedule(); >+ // wait until the job has a thread... >+ synchronized (latch) { >+ while (!latch[0].booleanValue()) { >+ try { >+ latch.wait(); >+ } catch (InterruptedException e) { >+ Thread.currentThread().interrupt(); >+ } >+ } >+ } >+ Job.getJobManager().transferRule(schedulingRule, >+ saveJob.getThread()); >+ ruleTransferred = true; >+ return; >+ } catch (CoreException e) { >+ ErrorDialog.openError(shellProvider.getShell(), >+ WorkbenchMessages.Error, e.getMessage(), e.getStatus()); >+ progressMonitor.setCanceled(true); >+ } >+ } finally { >+ if (!ruleTransferred) { >+ Job.getJobManager().endRule(schedulingRule); >+ } >+ progressMonitor.done(); >+ } >+ } >+ >+ public static void waitForBackgroundSaveJobs(List modelsToSave) { >+ // block if any of the saveables is still saving in the background >+ for (Iterator it = modelsToSave.iterator(); it.hasNext();) { >+ Saveable model = (Saveable) it.next(); >+ // Temporary safety check for 3.3M4: Only block if the saveable >+ // supports background save. >+ if (model.supportsBackgroundSave()) { >+ ISchedulingRule schedulingRule = ((InternalSaveable) model) >+ .getSchedulingRule(); >+ try { >+ Job.getJobManager().beginRule(schedulingRule, null); >+ // if the saveable is no longer dirty, remove it from the list >+ if (!model.isDirty()) { >+ it.remove(); >+ } >+ } finally { >+ Job.getJobManager().endRule(schedulingRule); >+ } >+ } >+ } >+ } >+ > } >Index: Eclipse UI/org/eclipse/ui/internal/EditorManager.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/EditorManager.java,v >retrieving revision 1.115 >diff -u -r1.115 EditorManager.java >--- Eclipse UI/org/eclipse/ui/internal/EditorManager.java 7 Dec 2006 14:46:55 -0000 1.115 >+++ Eclipse UI/org/eclipse/ui/internal/EditorManager.java 11 Dec 2006 04:34:15 -0000 >@@ -35,7 +35,6 @@ > import org.eclipse.core.runtime.SubProgressMonitor; > import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler; > import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker; >-import org.eclipse.jface.dialogs.ErrorDialog; > import org.eclipse.jface.dialogs.IDialogConstants; > import org.eclipse.jface.dialogs.MessageDialog; > import org.eclipse.jface.dialogs.ProgressMonitorDialog; >@@ -1105,7 +1104,7 @@ > * @return <code>true</code> on success, <code>false</code> if the user > * canceled the save > */ >- public static boolean saveAll(List dirtyParts, boolean confirm, boolean closing, >+ public static boolean saveAll(List dirtyParts, boolean confirm, final boolean closing, > boolean addNonPartSources, final IRunnableContext runnableContext, final IShellProvider shellProvider) { > // clone the input list > dirtyParts = new ArrayList(dirtyParts); >@@ -1205,6 +1204,7 @@ > if (modelsToSave.isEmpty()) { > return true; > } >+ SaveableHelper.waitForBackgroundSaveJobs(modelsToSave); > // Use a simpler dialog if there's only one > if (modelsToSave.size() == 1) { > Saveable model = (Saveable) modelsToSave.get(0); >@@ -1276,11 +1276,7 @@ > monitor.worked(1); > continue; > } >- try { >- model.doSave(new SubProgressMonitor(monitorWrap, 1)); >- } catch (CoreException e) { >- ErrorDialog.openError(shellProvider.getShell(), WorkbenchMessages.Error, e.getMessage(), e.getStatus()); >- } >+ SaveableHelper.doSaveModel(model, new SubProgressMonitor(monitorWrap, 1), shellProvider, closing); > if (monitorWrap.isCanceled()) { > break; > } >@@ -1294,7 +1290,7 @@ > 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 >Index: Eclipse UI/org/eclipse/ui/internal/SaveablesList.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/SaveablesList.java,v >retrieving revision 1.10 >diff -u -r1.10 SaveablesList.java >--- Eclipse UI/org/eclipse/ui/internal/SaveablesList.java 16 Aug 2006 03:24:12 -0000 1.10 >+++ Eclipse UI/org/eclipse/ui/internal/SaveablesList.java 11 Dec 2006 04:34:15 -0000 >@@ -21,11 +21,9 @@ > import java.util.Set; > > import org.eclipse.core.runtime.Assert; >-import org.eclipse.core.runtime.CoreException; > import org.eclipse.core.runtime.IProgressMonitor; > import org.eclipse.core.runtime.ListenerList; > import org.eclipse.core.runtime.SubProgressMonitor; >-import org.eclipse.jface.dialogs.ErrorDialog; > import org.eclipse.jface.dialogs.IDialogConstants; > import org.eclipse.jface.dialogs.MessageDialog; > import org.eclipse.jface.dialogs.MessageDialogWithToggle; >@@ -417,6 +415,7 @@ > final IWorkbenchWindow window, final boolean canCancel, boolean stillOpenElsewhere) { > // Save parts, exit the method if cancel is pressed. > if (modelsToSave.size() > 0) { >+ SaveableHelper.waitForBackgroundSaveJobs(modelsToSave); > > IPreferenceStore apiPreferenceStore = PrefUtil.getAPIPreferenceStore(); > boolean dontPrompt = stillOpenElsewhere && !apiPreferenceStore.getBoolean(IWorkbenchPreferenceConstants.PROMPT_WHEN_SAVEABLE_STILL_OPEN); >@@ -555,13 +554,7 @@ > monitor.worked(1); > continue; > } >- try { >- model.doSave(new SubProgressMonitor(monitorWrap, 1)); >- } catch (CoreException e) { >- ErrorDialog.openError(window.getShell(), >- WorkbenchMessages.Error, e.getMessage(), e >- .getStatus()); >- } >+ SaveableHelper.doSaveModel(model, new SubProgressMonitor(monitorWrap, 1), (WorkbenchWindow)window, true); > if (monitorWrap.isCanceled()) > break; > } >@@ -743,4 +736,19 @@ > .toArray(new ISaveablesSource[nonPartSources.size()]); > } > >+ /** >+ * @param model >+ */ >+ public IWorkbenchPart[] getPartsForSaveable(Saveable model) { >+ List result = new ArrayList(); >+ for (Iterator it = modelMap.entrySet().iterator(); it.hasNext();) { >+ Map.Entry entry = (Map.Entry) it.next(); >+ Set values = (Set) entry.getValue(); >+ if (values.contains(model) && entry.getKey() instanceof IWorkbenchPart) { >+ result.add(entry.getKey()); >+ } >+ } >+ return (IWorkbenchPart[]) result.toArray(new IWorkbenchPart[result.size()]); >+ } >+ > } >Index: Eclipse UI/org/eclipse/ui/Saveable.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/Saveable.java,v >retrieving revision 1.2 >diff -u -r1.2 Saveable.java >--- Eclipse UI/org/eclipse/ui/Saveable.java 11 Jul 2006 17:53:06 -0000 1.2 >+++ Eclipse UI/org/eclipse/ui/Saveable.java 11 Dec 2006 04:34:15 -0000 >@@ -13,7 +13,16 @@ > > import org.eclipse.core.runtime.CoreException; > import org.eclipse.core.runtime.IProgressMonitor; >+import org.eclipse.core.runtime.IStatus; > import org.eclipse.jface.resource.ImageDescriptor; >+import org.eclipse.jface.window.IShellProvider; >+import org.eclipse.swt.SWT; >+import org.eclipse.swt.graphics.Cursor; >+import org.eclipse.swt.widgets.Composite; >+import org.eclipse.swt.widgets.Control; >+import org.eclipse.ui.internal.InternalSaveable; >+import org.eclipse.ui.internal.PartSite; >+import org.eclipse.ui.progress.IJobRunnable; > > /** > * A <code>Saveable</code> represents a unit of saveability, e.g. an editable >@@ -32,17 +41,25 @@ > * @see ISaveablesSource > * @since 3.2 > */ >-public abstract class Saveable { >- >+public abstract class Saveable extends InternalSaveable { >+ >+ private Cursor waitCursor; >+ private Cursor originalCursor; >+ > /** >- * Attempts to show this saveable in the given page and returns <code>true</code> >- * on success. The default implementation does nothing and returns <code>false</code>. >+ * Attempts to show this saveable in the given page and returns >+ * <code>true</code> on success. The default implementation does nothing >+ * and returns <code>false</code>. > * >- * @param page the workbench page in which to show this saveable >+ * @param page >+ * the workbench page in which to show this saveable > * @return <code>true</code> if this saveable is now visible to the user > * @since 3.3 > */ > public boolean show(IWorkbenchPage page) { >+ if (page == null) { >+ // I wish it was easier to avoid warnings about unused parameters >+ } > return false; > } > >@@ -133,13 +150,156 @@ > * </p> > * > * <pre> >- * int PRIME = 31; >- * int hash = ...; // compute the "normal" hash code, e.g. based on some identifier unique within the defining plug-in >- * return hash * PRIME + MY_PLUGIN_ID.hashCode(); >+ * int PRIME = 31; >+ * int hash = ...; // compute the "normal" hash code, e.g. based on some identifier unique within the defining plug-in >+ * return hash * PRIME + MY_PLUGIN_ID.hashCode(); > * </pre> > * > * @return a hash code > */ > public abstract int hashCode(); > >+ /** >+ * Saves this saveable, or prepares this saveable for a background save >+ * operation. Returns null if this saveable has been successfully saved, or >+ * a job runnable that needs to be run to complete the save in the >+ * background. This method is called in the UI thread. If this saveable >+ * supports saving in the background, it should do only minimal work. >+ * However, since the job runnable returned by this method (if any) will not >+ * run on the UI thread, this method should copy any state that can only be >+ * accessed from the UI thread so that the job runnable will be able to >+ * access it. >+ * <p> >+ * The supplied shell provider can be used from within this method and from >+ * within the job runnable for the purpose of parenting dialogs. Care should >+ * be taken not to open dialogs gratuitously and only if user input is >+ * required for cases where the save cannot otherwise proceed - note that in >+ * any given save operation, many saveable objects may be saved at the same >+ * time. In particular, errors should be signaled by throwing an exception, >+ * or if an error occurs while running the job runnable, an error status >+ * should be returned. >+ * </p> >+ * <p> >+ * If the foreground part of the save is cancelled through user action, or >+ * for any other reason, the part should invoke <code>setCancelled</code> >+ * on the <code>IProgressMonitor</code> to inform the caller. If the >+ * background part of the save is cancelled, the job should return a >+ * {@link IStatus#CANCEL} status. >+ * </p> >+ * <p> >+ * This method is long-running; progress and cancellation are provided by >+ * the given progress monitor. >+ * </p> >+ * <p> >+ * The default implementation of this method calls >+ * {@link #doSave(IProgressMonitor)} and returns <code>null</code>. >+ * </p> >+ * >+ * @param monitor >+ * a progress monitor used for reporting progress and >+ * cancellation >+ * @param shellProvider >+ * an object that can provide a shell for parenting dialogs >+ * @return <code>null</code> if this saveable has been saved successfully, >+ * or a job runnable that needs to be run to complete the save in >+ * the background. >+ * >+ * @since 3.3 >+ */ >+ public IJobRunnable doSave(IProgressMonitor monitor, >+ IShellProvider shellProvider) throws CoreException { >+ doSave(monitor); >+ return null; >+ } >+ >+ /** >+ * Disables the UI of the given parts containing this saveable if necessary. >+ * This method is not intended to be called by clients. A corresponding call >+ * to >+ * <p> >+ * Saveables that can be saved in the background should ensure that the user >+ * cannot make changes to their data from the UI, for example by disabling >+ * controls, unless they are prepared to handle this case. This method is >+ * called on the UI thread after a job runnable has been returned from >+ * {@link #doSave(IProgressMonitor, IShellProvider, boolean)} and before >+ * spinning the event loop. The <code>closing</code> flag indicates that >+ * this saveable is currently being saved in response to closing a workbench >+ * part, in which case further changes to this saveable through the UI must >+ * be prevented. >+ * </p> >+ * <p> >+ * The default implementation calls setEnabled(false) on the given parts' >+ * composites. >+ * </p> >+ * >+ * @param parts >+ * the workbench parts containing this saveable >+ * @param closing >+ * a boolean flag indicating whether the save was triggered by a >+ * request to close a workbench part, and all of the given parts >+ * will be closed after the save operation finishes successfully. >+ * >+ * @since 3.3 >+ */ >+ public void disableUI(IWorkbenchPart[] parts, boolean closing) { >+ for (int i = 0; i < parts.length; i++) { >+ IWorkbenchPart workbenchPart = parts[i]; >+ Composite paneComposite = (Composite) ((PartSite) workbenchPart >+ .getSite()).getPane().getControl(); >+ Control[] paneChildren = paneComposite.getChildren(); >+ Composite toDisable = ((Composite) paneChildren[0]); >+ toDisable.setEnabled(false); >+ if (waitCursor == null) { >+ waitCursor = new Cursor(workbenchPart.getSite().getWorkbenchWindow().getShell().getDisplay(), SWT.CURSOR_WAIT); >+ } >+ originalCursor = paneComposite.getCursor(); >+ paneComposite.setCursor(waitCursor); >+ } >+ } >+ >+ /** >+ * Enables the UI of the given parts containing this saveable after a >+ * background save operation has finished. This method is not intended to be >+ * called by clients. >+ * <p> >+ * The default implementation calls setEnabled(true) on the given parts' >+ * composites. >+ * </p> >+ * >+ * @param parts >+ * the workbench parts containing this saveable >+ * >+ * @since 3.3 >+ */ >+ public void enableUI(IWorkbenchPart[] parts) { >+ for (int i = 0; i < parts.length; i++) { >+ IWorkbenchPart workbenchPart = parts[i]; >+ Composite paneComposite = (Composite) ((PartSite) workbenchPart >+ .getSite()).getPane().getControl(); >+ Control[] paneChildren = paneComposite.getChildren(); >+ Composite toEnable = ((Composite) paneChildren[0]); >+ paneComposite.setCursor(originalCursor); >+ if (waitCursor!=null && !waitCursor.isDisposed()) { >+ waitCursor.dispose(); >+ waitCursor = null; >+ } >+ toEnable.setEnabled(true); >+ } >+ } >+ >+ /** >+ * EXPERIMENTAL / TEMPORARY: This method will very likely be removed before >+ * 3.3 M5. As of 3.3 M4, clients must override this method and return true >+ * if their implementation of >+ * {@link #doSave(IProgressMonitor, IShellProvider)} may return a non-null >+ * result. The default implementation returns false. >+ * >+ * @return <code>true</code> if this saveable may return a non-null value >+ * from {@link #doSave(IProgressMonitor, IShellProvider)}. >+ * >+ * @since 3.3 >+ */ >+ public boolean supportsBackgroundSave() { >+ return false; >+ } > } >Index: Eclipse UI/org/eclipse/ui/progress/IJobRunnable.java >=================================================================== >RCS file: Eclipse UI/org/eclipse/ui/progress/IJobRunnable.java >diff -N Eclipse UI/org/eclipse/ui/progress/IJobRunnable.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ Eclipse UI/org/eclipse/ui/progress/IJobRunnable.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,42 @@ >+/******************************************************************************* >+ * Copyright (c) 2006 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.progress; >+ >+import org.eclipse.core.runtime.IProgressMonitor; >+import org.eclipse.core.runtime.IStatus; >+ >+/** >+ * Interface for runnables that can be run as jobs. >+ * >+ * @since 3.3 >+ */ >+public interface IJobRunnable { >+ >+ /** >+ * Executes this runnable. Returns the result of the execution. >+ * <p> >+ * The provided monitor can be used to report progress and respond to >+ * cancellation. If the progress monitor has been canceled, the runnable should >+ * finish its execution at the earliest convenience and return a result >+ * status of severity <code>IStatus.CANCEL</code>. The singleton cancel >+ * status <code>Status.CANCEL_STATUS</code> can be used for this purpose. >+ * <p> >+ * >+ * @param monitor >+ * the monitor to be used for reporting progress and responding >+ * to cancelation. The monitor is never <code>null</code> >+ * @return resulting status of the run. The result must not be >+ * <code>null</code> >+ */ >+ public IStatus run(IProgressMonitor monitor); >+ >+} >Index: Eclipse UI/org/eclipse/ui/internal/IBackgroundSaveListener.java >=================================================================== >RCS file: Eclipse UI/org/eclipse/ui/internal/IBackgroundSaveListener.java >diff -N Eclipse UI/org/eclipse/ui/internal/IBackgroundSaveListener.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ Eclipse UI/org/eclipse/ui/internal/IBackgroundSaveListener.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,22 @@ >+/******************************************************************************* >+ * Copyright (c) 2006 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; >+ >+/** >+ * @since 3.3 >+ * >+ */ >+interface IBackgroundSaveListener { >+ >+ public void handleBackgroundSaveStarted(); >+ >+} >Index: Eclipse UI/org/eclipse/ui/internal/InternalSaveable.java >=================================================================== >RCS file: Eclipse UI/org/eclipse/ui/internal/InternalSaveable.java >diff -N Eclipse UI/org/eclipse/ui/internal/InternalSaveable.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ Eclipse UI/org/eclipse/ui/internal/InternalSaveable.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,77 @@ >+/******************************************************************************* >+ * Copyright (c) 2006 IBM Corporation and others. >+ * All rights reserved. This program and the accompanying materials >+ * are made available under the terms of the Eclipse Public License v1.0 >+ * which accompanies this distribution, and is available at >+ * http://www.eclipse.org/legal/epl-v10.html >+ * >+ * Contributors: >+ * IBM Corporation - initial API and implementation >+ ******************************************************************************/ >+ >+package org.eclipse.ui.internal; >+ >+import org.eclipse.core.runtime.jobs.ISchedulingRule; >+ >+/** >+ * @since 3.3 >+ * >+ */ >+public class InternalSaveable { >+ >+ static class SerialPerObjectRule implements ISchedulingRule { >+ >+ private InternalSaveable lockObject = null; >+ >+ public SerialPerObjectRule(InternalSaveable lock) { >+ lockObject = lock; >+ } >+ >+ /* >+ * (non-Javadoc) >+ * >+ * @see org.eclipse.core.runtime.jobs.ISchedulingRule#contains(org.eclipse.core.runtime.jobs.ISchedulingRule) >+ */ >+ public boolean contains(ISchedulingRule rule) { >+ return rule == this; >+ } >+ >+ /* >+ * (non-Javadoc) >+ * >+ * @see org.eclipse.core.runtime.jobs.ISchedulingRule#isConflicting(org.eclipse.core.runtime.jobs.ISchedulingRule) >+ */ >+ public boolean isConflicting(ISchedulingRule rule) { >+ if (rule instanceof SerialPerObjectRule) { >+ SerialPerObjectRule otherRule = (SerialPerObjectRule) rule; >+ return lockObject.equals(otherRule.lockObject); >+ } >+ return false; >+ } >+ >+ } >+ >+ private boolean savingInBackground; >+ >+ /** >+ * @return Returns the lock. >+ */ >+ /* package */ISchedulingRule getSchedulingRule() { >+ return new SerialPerObjectRule(this); >+ } >+ >+ /** >+ * @return >+ */ >+ /* package */ boolean isSavingInBackground() { >+ return savingInBackground; >+ } >+ >+ /** >+ * @param savingInBackground The savingInBackground to set. >+ */ >+ /* package */ void setSavingInBackground(boolean savingInBackground) { >+ this.savingInBackground = savingInBackground; >+ } >+ >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 154122
:
52912
|
53784
|
55172
| 55378