001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.ui.refactoring;
011:
012: import java.lang.reflect.InvocationTargetException;
013: import java.util.Arrays;
014:
015: import org.eclipse.core.runtime.Assert;
016: import org.eclipse.core.runtime.CoreException;
017: import org.eclipse.core.runtime.IProgressMonitor;
018: import org.eclipse.core.runtime.SubProgressMonitor;
019:
020: import org.eclipse.core.resources.IWorkspace;
021: import org.eclipse.core.resources.IWorkspaceDescription;
022: import org.eclipse.core.resources.IncrementalProjectBuilder;
023: import org.eclipse.core.resources.ResourcesPlugin;
024:
025: import org.eclipse.swt.SWT;
026: import org.eclipse.swt.events.SelectionAdapter;
027: import org.eclipse.swt.events.SelectionEvent;
028: import org.eclipse.swt.graphics.Image;
029: import org.eclipse.swt.widgets.Button;
030: import org.eclipse.swt.widgets.Composite;
031: import org.eclipse.swt.widgets.Control;
032: import org.eclipse.swt.widgets.Shell;
033:
034: import org.eclipse.jface.operation.IRunnableWithProgress;
035: import org.eclipse.jface.viewers.ArrayContentProvider;
036: import org.eclipse.jface.viewers.ILabelProvider;
037: import org.eclipse.jface.viewers.LabelProvider;
038: import org.eclipse.jface.window.Window;
039:
040: import org.eclipse.ui.IEditorPart;
041: import org.eclipse.ui.PlatformUI;
042: import org.eclipse.ui.actions.GlobalBuildAction;
043:
044: import org.eclipse.jdt.internal.ui.JavaPlugin;
045: import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
046: import org.eclipse.jdt.internal.ui.refactoring.actions.ListDialog;
047: import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
048:
049: public class RefactoringSaveHelper {
050:
051: private boolean fFilesSaved;
052: private final int fSaveMode;
053:
054: /**
055: * Save mode to save all dirty editors (always ask).
056: */
057: public static final int SAVE_ALL_ALWAYS_ASK = 1;
058:
059: /**
060: * Save mode to save all dirty editors.
061: */
062: public static final int SAVE_ALL = 2;
063:
064: /**
065: * Save mode to save all unknown editors, i.e. those that don't work on
066: * resources, don't use file buffers, or are otherwise suspect.
067: *
068: * Used for refactorings with participants or qualified name updating.
069: */
070: public static final int SAVE_NON_JAVA_UPDATES = 3;
071:
072: /**
073: * Save mode to save only dirty editors on compilation units that are not in
074: * working copy mode.
075: *
076: * Used for refactorings without participants or qualified name updating.
077: */
078: public static final int SAVE_JAVA_ONLY_UPDATES = 4;
079:
080: /**
081: * Save mode to not save save any editors.
082: */
083: public static final int SAVE_NOTHING = 5;
084:
085: /**
086: * @param saveMode one of the SAVE_* constants
087: */
088: public RefactoringSaveHelper(int saveMode) {
089: Assert.isTrue(saveMode == SAVE_ALL_ALWAYS_ASK
090: || saveMode == SAVE_ALL
091: || saveMode == SAVE_NON_JAVA_UPDATES
092: || saveMode == SAVE_JAVA_ONLY_UPDATES
093: || saveMode == SAVE_NOTHING);
094: fSaveMode = saveMode;
095: }
096:
097: /**
098: * @param shell
099: * @return <code>true</code> if save was successful and refactoring can proceed;
100: * false if the refactoring must be cancelled
101: */
102: public boolean saveEditors(Shell shell) {
103: final IEditorPart[] dirtyEditors;
104: switch (fSaveMode) {
105: case SAVE_ALL_ALWAYS_ASK:
106: case SAVE_ALL:
107: dirtyEditors = EditorUtility.getDirtyEditors(true);
108: break;
109:
110: case SAVE_NON_JAVA_UPDATES:
111: dirtyEditors = EditorUtility.getDirtyEditorsToSave(false); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=175495
112: break;
113:
114: case SAVE_JAVA_ONLY_UPDATES:
115: dirtyEditors = EditorUtility.getDirtyEditorsToSave(false);
116: break;
117:
118: case SAVE_NOTHING:
119: return true;
120:
121: default:
122: throw new IllegalStateException(Integer.toString(fSaveMode));
123: }
124: if (dirtyEditors.length == 0)
125: return true;
126: if (!askSaveAllDirtyEditors(shell, dirtyEditors))
127: return false;
128: try {
129: // Save isn't cancelable.
130: IWorkspace workspace = ResourcesPlugin.getWorkspace();
131: IWorkspaceDescription description = workspace
132: .getDescription();
133: boolean autoBuild = description.isAutoBuilding();
134: description.setAutoBuilding(false);
135: workspace.setDescription(description);
136: try {
137: if (fSaveMode == SAVE_ALL_ALWAYS_ASK
138: || fSaveMode == SAVE_ALL
139: || RefactoringSavePreferences
140: .getSaveAllEditors()) {
141: if (!JavaPlugin.getActiveWorkbenchWindow()
142: .getWorkbench().saveAllEditors(false))
143: return false;
144: } else {
145: IRunnableWithProgress runnable = new IRunnableWithProgress() {
146: public void run(IProgressMonitor pm)
147: throws InterruptedException {
148: int count = dirtyEditors.length;
149: pm.beginTask("", count); //$NON-NLS-1$
150: for (int i = 0; i < count; i++) {
151: IEditorPart editor = dirtyEditors[i];
152: editor.doSave(new SubProgressMonitor(
153: pm, 1));
154: if (pm.isCanceled())
155: throw new InterruptedException();
156: }
157: pm.done();
158: }
159: };
160: try {
161: PlatformUI
162: .getWorkbench()
163: .getProgressService()
164: .runInUI(
165: JavaPlugin
166: .getActiveWorkbenchWindow(),
167: runnable, null);
168: } catch (InterruptedException e) {
169: return false;
170: } catch (InvocationTargetException e) {
171: ExceptionHandler
172: .handle(
173: e,
174: shell,
175: RefactoringMessages.RefactoringStarter_saving,
176: RefactoringMessages.RefactoringStarter_unexpected_exception);
177: return false;
178: }
179: }
180: fFilesSaved = true;
181: } finally {
182: description.setAutoBuilding(autoBuild);
183: workspace.setDescription(description);
184: }
185: return true;
186: } catch (CoreException e) {
187: ExceptionHandler
188: .handle(
189: e,
190: shell,
191: RefactoringMessages.RefactoringStarter_saving,
192: RefactoringMessages.RefactoringStarter_unexpected_exception);
193: return false;
194: }
195: }
196:
197: public void triggerBuild() {
198: if (fFilesSaved
199: && ResourcesPlugin.getWorkspace().getDescription()
200: .isAutoBuilding()) {
201: new GlobalBuildAction(
202: JavaPlugin.getActiveWorkbenchWindow(),
203: IncrementalProjectBuilder.INCREMENTAL_BUILD).run();
204: }
205: }
206:
207: private boolean askSaveAllDirtyEditors(Shell shell,
208: IEditorPart[] dirtyEditors) {
209: final boolean canSaveAutomatically = fSaveMode != SAVE_ALL_ALWAYS_ASK;
210: if (canSaveAutomatically
211: && RefactoringSavePreferences.getSaveAllEditors()) //must save everything
212: return true;
213: ListDialog dialog = new ListDialog(shell) {
214: {
215: setShellStyle(getShellStyle() | SWT.APPLICATION_MODAL);
216: }
217:
218: protected Control createDialogArea(Composite parent) {
219: Composite result = (Composite) super
220: .createDialogArea(parent);
221: if (canSaveAutomatically) {
222: final Button check = new Button(result, SWT.CHECK);
223: check
224: .setText(RefactoringMessages.RefactoringStarter_always_save);
225: check.setSelection(RefactoringSavePreferences
226: .getSaveAllEditors());
227: check.addSelectionListener(new SelectionAdapter() {
228: public void widgetSelected(SelectionEvent e) {
229: RefactoringSavePreferences
230: .setSaveAllEditors(check
231: .getSelection());
232: }
233: });
234: applyDialogFont(result);
235: }
236: return result;
237: }
238: };
239: dialog
240: .setTitle(RefactoringMessages.RefactoringStarter_save_all_resources);
241: dialog.setAddCancelButton(true);
242: dialog.setLabelProvider(createDialogLabelProvider());
243: dialog
244: .setMessage(RefactoringMessages.RefactoringStarter_must_save);
245: dialog.setContentProvider(new ArrayContentProvider());
246: dialog.setInput(Arrays.asList(dirtyEditors));
247: return dialog.open() == Window.OK;
248: }
249:
250: public boolean hasFilesSaved() {
251: return fFilesSaved;
252: }
253:
254: private ILabelProvider createDialogLabelProvider() {
255: return new LabelProvider() {
256: public Image getImage(Object element) {
257: return ((IEditorPart) element).getTitleImage();
258: }
259:
260: public String getText(Object element) {
261: return ((IEditorPart) element).getTitle();
262: }
263: };
264: }
265: }
|