KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > actions > CloseResourceAction


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.actions;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.core.resources.IFile;
19 import org.eclipse.core.resources.IProject;
20 import org.eclipse.core.resources.IResource;
21 import org.eclipse.core.resources.IResourceChangeEvent;
22 import org.eclipse.core.resources.IResourceChangeListener;
23 import org.eclipse.core.resources.IResourceDelta;
24 import org.eclipse.core.resources.IResourceRuleFactory;
25 import org.eclipse.core.resources.ResourcesPlugin;
26 import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
27 import org.eclipse.core.resources.mapping.ResourceChangeValidator;
28 import org.eclipse.core.runtime.CoreException;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.core.runtime.NullProgressMonitor;
31 import org.eclipse.core.runtime.jobs.ISchedulingRule;
32 import org.eclipse.core.runtime.jobs.MultiRule;
33 import org.eclipse.jface.dialogs.IDialogConstants;
34 import org.eclipse.jface.viewers.IStructuredSelection;
35 import org.eclipse.osgi.util.NLS;
36 import org.eclipse.swt.custom.BusyIndicator;
37 import org.eclipse.swt.widgets.Shell;
38 import org.eclipse.ui.IEditorPart;
39 import org.eclipse.ui.IWorkbenchPage;
40 import org.eclipse.ui.IWorkbenchWindow;
41 import org.eclipse.ui.PlatformUI;
42 import org.eclipse.ui.dialogs.ListSelectionDialog;
43 import org.eclipse.ui.ide.IDE;
44 import org.eclipse.ui.ide.ResourceUtil;
45 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
46 import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
47 import org.eclipse.ui.model.AdaptableList;
48 import org.eclipse.ui.model.WorkbenchContentProvider;
49 import org.eclipse.ui.model.WorkbenchPartLabelProvider;
50
51 /**
52  * Standard action for closing the currently selected project(s).
53  * <p>
54  * This class may be instantiated; it is not intended to be subclassed.
55  * </p>
56  */

57 public class CloseResourceAction extends WorkspaceAction implements
58         IResourceChangeListener {
59     /**
60      * The id of this action.
61      */

62     public static final String JavaDoc ID = PlatformUI.PLUGIN_ID
63             + ".CloseResourceAction"; //$NON-NLS-1$
64
private String JavaDoc[] modelProviderIds;
65
66     /**
67      * Creates a new action.
68      *
69      * @param shell the shell for any dialogs
70      */

71     public CloseResourceAction(Shell shell) {
72         super(shell, IDEWorkbenchMessages.CloseResourceAction_text);
73         setId(ID);
74         setToolTipText(IDEWorkbenchMessages.CloseResourceAction_toolTip);
75         PlatformUI.getWorkbench().getHelpSystem().setHelp(this,
76                 IIDEHelpContextIds.CLOSE_RESOURCE_ACTION);
77     }
78     
79     /**
80      * Override super constructor to allow subclass to
81      * override with unique text.
82      */

83     protected CloseResourceAction(Shell shell, String JavaDoc text) {
84         super(shell, text);
85     }
86
87     /**
88      * Return a list of dirty editors associated with the given projects. Return
89      * editors from all perspectives.
90      *
91      * @return List the dirty editors
92      */

93     List JavaDoc getDirtyEditors(List JavaDoc projects) {
94         List JavaDoc dirtyEditors = new ArrayList JavaDoc(0);
95         IWorkbenchWindow[] windows = PlatformUI.getWorkbench()
96                 .getWorkbenchWindows();
97         for (int i = 0; i < windows.length; i++) {
98             IWorkbenchPage[] pages = windows[i].getPages();
99             for (int j = 0; j < pages.length; j++) {
100                 IWorkbenchPage page = pages[j];
101                 IEditorPart[] editors = page.getDirtyEditors();
102                 for (int k = 0; k < editors.length; k++) {
103                     IEditorPart editor = editors[k];
104                     IFile inputFile = ResourceUtil.getFile(editor.getEditorInput());
105                     if (inputFile != null) {
106                         if (projects.contains(inputFile.getProject())) {
107                             dirtyEditors.add(editor);
108                         }
109                     }
110                 }
111             }
112         }
113         return dirtyEditors;
114     }
115
116     /**
117      * Open a dialog that can be used to select which of the given
118      * editors to save. Return the list of editors to save. A value of
119      * null implies that the operation was cancelled.
120      *
121      * @return List the editors to save
122      */

123     List JavaDoc getEditorsToSave(List JavaDoc dirtyEditors) {
124         if (dirtyEditors.isEmpty()) {
125             return new ArrayList JavaDoc(0);
126         }
127
128         // The list may have multiple editors opened for the same input,
129
// so process the list for duplicates.
130
List JavaDoc saveEditors = new ArrayList JavaDoc(0);
131         List JavaDoc dirtyInputs = new ArrayList JavaDoc(0);
132         Iterator JavaDoc iter = dirtyEditors.iterator();
133         while (iter.hasNext()) {
134             IEditorPart editor = (IEditorPart) iter.next();
135             IFile inputFile = ResourceUtil.getFile(editor.getEditorInput());
136             if (inputFile != null) {
137                 // if the same file is open in multiple perspectives,
138
// we don't want to count it as dirty multiple times
139
if (!dirtyInputs.contains(inputFile)) {
140                     dirtyInputs.add(inputFile);
141                     saveEditors.add(editor);
142                 }
143             }
144         }
145         AdaptableList input = new AdaptableList(saveEditors);
146         ListSelectionDialog dlg = new ListSelectionDialog(getShell(), input,
147                 new WorkbenchContentProvider(),
148                 new WorkbenchPartLabelProvider(), IDEWorkbenchMessages.EditorManager_saveResourcesMessage);
149
150         dlg.setInitialSelections(saveEditors.toArray(new Object JavaDoc[saveEditors
151                 .size()]));
152         dlg.setTitle(IDEWorkbenchMessages.EditorManager_saveResourcesTitle);
153         int result = dlg.open();
154
155         if (result == IDialogConstants.CANCEL_ID) {
156             return null;
157         }
158         return Arrays.asList(dlg.getResult());
159     }
160
161     /* (non-Javadoc)
162      * Method declared on WorkspaceAction.
163      */

164     protected String JavaDoc getOperationMessage() {
165         return IDEWorkbenchMessages.CloseResourceAction_operationMessage;
166     }
167
168     /* (non-Javadoc)
169      * Method declared on WorkspaceAction.
170      */

171     protected String JavaDoc getProblemsMessage() {
172         return IDEWorkbenchMessages.CloseResourceAction_problemMessage;
173     }
174
175     /* (non-Javadoc)
176      * Method declared on WorkspaceAction.
177      */

178     protected String JavaDoc getProblemsTitle() {
179         return IDEWorkbenchMessages.CloseResourceAction_title;
180     }
181
182     protected void invokeOperation(IResource resource, IProgressMonitor monitor)
183             throws CoreException {
184         ((IProject) resource).close(monitor);
185     }
186
187     /**
188      * The implementation of this <code>WorkspaceAction</code> method
189      * method saves and closes the resource's dirty editors before closing
190      * it.
191      */

192     public void run() {
193         if (!saveDirtyEditors()) {
194             return;
195         }
196         if (!validateClose()) {
197             return;
198         }
199         //be conservative and include all projects in the selection - projects
200
//can change state between now and when the job starts
201
ISchedulingRule rule = null;
202         IResourceRuleFactory factory = ResourcesPlugin.getWorkspace().getRuleFactory();
203         Iterator JavaDoc resources = getSelectedResources().iterator();
204         while (resources.hasNext()) {
205             IProject project = (IProject) resources.next();
206             rule = MultiRule.combine(rule, factory.modifyRule(project));
207         }
208         runInBackground(rule);
209     }
210
211     /**
212      * Causes all dirty editors associated to the resource(s) to be saved, if so
213      * specified by the user, and closed.
214      */

215     boolean saveDirtyEditors() {
216         // Get the items to close.
217
List JavaDoc projects = getSelectedResources();
218         if (projects == null || projects.isEmpty()) {
219             // no action needs to be taken since no projects are selected
220
return false;
221         }
222
223         // Collect all the dirty editors that are associated to the projects that are
224
// to be closed.
225
final List JavaDoc dirtyEditors = getDirtyEditors(projects);
226
227         // See which editors should be saved.
228
final List JavaDoc saveEditors = getEditorsToSave(dirtyEditors);
229         if (saveEditors == null) {
230             // the operation was cancelled
231
return false;
232         }
233
234         // Save and close the dirty editors.
235
BusyIndicator.showWhile(getShell().getDisplay(), new Runnable JavaDoc() {
236             public void run() {
237                 Iterator JavaDoc iter = dirtyEditors.iterator();
238                 while (iter.hasNext()) {
239                     IEditorPart editor = (IEditorPart) iter.next();
240                     IWorkbenchPage page = editor.getEditorSite().getPage();
241                     if (saveEditors.contains(editor)) {
242                         // do a direct save vs. using page.saveEditor, so that
243
// progress dialogs do not flash up on the screen multiple
244
// times
245
editor.doSave(new NullProgressMonitor());
246                     }
247                     page.closeEditor(editor, false);
248                 }
249             }
250         });
251
252         return true;
253     }
254
255     /* (non-Javadoc)
256      * Method declared on WorkspaceAction.
257      */

258     protected boolean shouldPerformResourcePruning() {
259         return false;
260     }
261
262     /**
263      * The <code>CloseResourceAction</code> implementation of this
264      * <code>SelectionListenerAction</code> method ensures that this action is
265      * enabled only if one of the selections is an open project.
266      */

267     protected boolean updateSelection(IStructuredSelection s) {
268         // don't call super since we want to enable if open project is selected.
269
if (!selectionIsOfType(IResource.PROJECT)) {
270             return false;
271         }
272
273         Iterator JavaDoc resources = getSelectedResources().iterator();
274         while (resources.hasNext()) {
275             IProject currentResource = (IProject) resources.next();
276             if (currentResource.isOpen()) {
277                 return true;
278             }
279         }
280         return false;
281     }
282
283     /**
284      * Handles a resource changed event by updating the enablement
285      * if one of the selected projects is opened or closed.
286      */

287     public void resourceChanged(IResourceChangeEvent event) {
288         // Warning: code duplicated in OpenResourceAction
289
List JavaDoc sel = getSelectedResources();
290         // don't bother looking at delta if selection not applicable
291
if (selectionIsOfType(IResource.PROJECT)) {
292             IResourceDelta delta = event.getDelta();
293             if (delta != null) {
294                 IResourceDelta[] projDeltas = delta
295                         .getAffectedChildren(IResourceDelta.CHANGED);
296                 for (int i = 0; i < projDeltas.length; ++i) {
297                     IResourceDelta projDelta = projDeltas[i];
298                     if ((projDelta.getFlags() & IResourceDelta.OPEN) != 0) {
299                         if (sel.contains(projDelta.getResource())) {
300                             selectionChanged(getStructuredSelection());
301                             return;
302                         }
303                     }
304                 }
305             }
306         }
307     }
308     
309     /**
310      * Returns the model provider ids that are known to the client
311      * that instantiated this operation.
312      *
313      * @return the model provider ids that are known to the client
314      * that instantiated this operation.
315      * @since 3.2
316      */

317     public String JavaDoc[] getModelProviderIds() {
318         return modelProviderIds;
319     }
320
321     /**
322      * Sets the model provider ids that are known to the client
323      * that instantiated this operation. Any potential side effects
324      * reported by these models during validation will be ignored.
325      *
326      * @param modelProviderIds the model providers known to the client
327      * who is using this operation.
328      * @since 3.2
329      */

330     public void setModelProviderIds(String JavaDoc[] modelProviderIds) {
331         this.modelProviderIds = modelProviderIds;
332     }
333     
334     /**
335      * Validates the operation against the model providers.
336      *
337      * @return whether the operation should proceed
338      */

339     private boolean validateClose() {
340         IResourceChangeDescriptionFactory factory = ResourceChangeValidator.getValidator().createDeltaFactory();
341         List JavaDoc resources = getActionResources();
342         for (Iterator JavaDoc iter = resources.iterator(); iter.hasNext();) {
343             IResource resource = (IResource) iter.next();
344             if (resource instanceof IProject) {
345                 IProject project = (IProject) resource;
346                 factory.close(project);
347             }
348         }
349         String JavaDoc message;
350         if (resources.size() == 1) {
351             message = NLS.bind(IDEWorkbenchMessages.CloseResourceAction_warningForOne, ((IResource)resources.get(0)).getName());
352         } else {
353             message = IDEWorkbenchMessages.CloseResourceAction_warningForMultiple;
354         }
355         return IDE.promptToConfirm(getShell(), IDEWorkbenchMessages.CloseResourceAction_confirm, message, factory.getDelta(), getModelProviderIds(), false /* no need to syncExec */);
356     }
357 }
358
Popular Tags