blob: 317fe1eb5c0999d6ef58244a95c9e07e7949b1dd [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2009 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
* Mohamed Tarief , IBM - Bug 139211
*******************************************************************************/
package org.eclipse.ui.actions;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.ide.IDEInternalPreferences;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
/**
* Standard action for opening the currently selected project(s).
* <p>
* Note that there is a different action for opening an editor on file
* resources: <code>OpenFileAction</code>.
* </p>
* <p>
* This class may be instantiated; it is not intended to be subclassed.
* </p>
* @noextend This class is not intended to be subclassed by clients.
*/
public class OpenResourceAction extends WorkspaceAction implements IResourceChangeListener {
/**
* The id of this action.
*/
public static final String ID = PlatformUI.PLUGIN_ID + ".OpenResourceAction"; //$NON-NLS-1$
/**
* Creates a new action.
*
* @param shell
* the shell for any dialogs
*
* @deprecated {@link #OpenResourceAction(IShellProvider)}
*/
public OpenResourceAction(Shell shell) {
super(shell, IDEWorkbenchMessages.OpenResourceAction_text);
initAction();
}
/**
* Creates a new action.
*
* @param provider
* the shell for any dialogs
* @since 3.4
*/
public OpenResourceAction(IShellProvider provider) {
super(provider, IDEWorkbenchMessages.OpenResourceAction_text);
initAction();
}
/**
* Initializes the workbench
*/
private void initAction() {
PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IIDEHelpContextIds.OPEN_RESOURCE_ACTION);
setToolTipText(IDEWorkbenchMessages.OpenResourceAction_toolTip);
setId(ID);
}
/**
* Returns the total number of closed projects in the workspace.
*/
private int countClosedProjects() {
int count = 0;
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for (int i = 0; i < projects.length; i++) {
if (!projects[i].isOpen()) {
count++;
}
}
return count;
}
/*
* (non-Javadoc) Method declared on WorkspaceAction.
*/
protected String getOperationMessage() {
return IDEWorkbenchMessages.OpenResourceAction_operationMessage;
}
/*
* (non-Javadoc) Method declared on WorkspaceAction.
*/
protected String getProblemsMessage() {
return IDEWorkbenchMessages.OpenResourceAction_problemMessage;
}
/*
* (non-Javadoc) Method declared on WorkspaceAction.
*/
protected String getProblemsTitle() {
return IDEWorkbenchMessages.OpenResourceAction_dialogTitle;
}
/**
* Returns whether there are closed projects in the workspace that are
* not part of the current selection.
*/
private boolean hasOtherClosedProjects() {
//count the closed projects in the selection
int closedInSelection = 0;
Iterator resources = getSelectedResources().iterator();
while (resources.hasNext()) {
IProject project = (IProject) resources.next();
if (!project.isOpen())
closedInSelection++;
}
//there are other closed projects if the selection does
//not contain all closed projects in the workspace
return closedInSelection < countClosedProjects();
}
protected void invokeOperation(IResource resource, IProgressMonitor monitor) throws CoreException {
((IProject) resource).open(monitor);
}
/**
* Returns the preference for whether to open required projects when opening
* a project. Consults the preference and prompts the user if necessary.
*
* @return <code>true</code> if referenced projects should be opened, and
* <code>false</code> otherwise.
*/
private boolean promptToOpenWithReferences() {
IPreferenceStore store = IDEWorkbenchPlugin.getDefault().getPreferenceStore();
String key = IDEInternalPreferences.OPEN_REQUIRED_PROJECTS;
String value = store.getString(key);
if (MessageDialogWithToggle.ALWAYS.equals(value)) {
return true;
}
if (MessageDialogWithToggle.NEVER.equals(value)) {
return false;
}
String message = IDEWorkbenchMessages.OpenResourceAction_openRequiredProjects;
MessageDialogWithToggle dialog = MessageDialogWithToggle.openYesNoCancelQuestion(getShell(), IDEWorkbenchMessages.Question, message, null, false, store, key);
int result = dialog.getReturnCode();
// the result is equal to SWT.DEFAULT if the user uses the 'esc' key to close the dialog
if (result == Window.CANCEL || result == SWT.DEFAULT) {
throw new OperationCanceledException();
}
return dialog.getReturnCode() == IDialogConstants.YES_ID;
}
/**
* Handles a resource changed event by updating the enablement if one of the
* selected projects is opened or closed.
*/
public void resourceChanged(IResourceChangeEvent event) {
// Warning: code duplicated in CloseResourceAction
List sel = getSelectedResources();
// don't bother looking at delta if selection not applicable
if (selectionIsOfType(IResource.PROJECT)) {
IResourceDelta delta = event.getDelta();
if (delta != null) {
IResourceDelta[] projDeltas = delta.getAffectedChildren(IResourceDelta.CHANGED);
for (int i = 0; i < projDeltas.length; ++i) {
IResourceDelta projDelta = projDeltas[i];
if ((projDelta.getFlags() & IResourceDelta.OPEN) != 0) {
if (sel.contains(projDelta.getResource())) {
selectionChanged(getStructuredSelection());
return;
}
}
}
}
}
}
/*
* (non-Javadoc) Method declared on IAction; overrides method on
* WorkspaceAction.
*/
public void run() {
try {
runOpenWithReferences();
} catch (OperationCanceledException e) {
//just return when canceled
}
}
/**
* Opens the selected projects, and all related projects, in the background.
*/
private void runOpenWithReferences() {
final List resources = new ArrayList(getActionResources());
Job job = new WorkspaceJob(removeMnemonics(getText())) {
private boolean openProjectReferences = true;
private boolean hasPrompted = false;
/**
* Opens a project along with all projects it references
*/
private void doOpenWithReferences(IProject project, IProgressMonitor monitor) throws CoreException {
if (!project.exists() || project.isOpen()) {
return;
}
project.open(new SubProgressMonitor(monitor, 1000));
final IProject[] references = project.getReferencedProjects();
if (!hasPrompted) {
openProjectReferences = false;
for (int i = 0; i < references.length; i++) {
if (references[i].exists() && !references[i].isOpen()) {
openProjectReferences = true;
break;
}
}
if (openProjectReferences && hasOtherClosedProjects()) {
Display.getDefault().syncExec(new Runnable() {
public void run() {
openProjectReferences = promptToOpenWithReferences();
//remember that we have prompted to avoid repeating the analysis
hasPrompted = true;
}
});
}
}
if (openProjectReferences) {
for (int i = 0; i < references.length; i++) {
doOpenWithReferences(references[i], monitor);
}
}
}
public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
try {
// at most we can only open all projects currently closed
monitor.beginTask("", countClosedProjects() * 1000); //$NON-NLS-1$
monitor.setTaskName(getOperationMessage());
for (Iterator it = resources.iterator(); it.hasNext();) {
doOpenWithReferences((IProject) it.next(), monitor);
}
} finally {
monitor.done();
}
return Status.OK_STATUS;
}
};
job.setRule(ResourcesPlugin.getWorkspace().getRoot());
job.setUser(true);
job.schedule();
}
/*
* (non-Javadoc) Method declared on WorkspaceAction.
*/
protected boolean shouldPerformResourcePruning() {
return false;
}
/**
* The <code>OpenResourceAction</code> implementation of this
* <code>SelectionListenerAction</code> method ensures that this action is
* enabled only if one of the selections is a closed project.
*/
protected boolean updateSelection(IStructuredSelection s) {
// don't call super since we want to enable if closed project is
// selected.
if (!selectionIsOfType(IResource.PROJECT)) {
return false;
}
Iterator resources = getSelectedResources().iterator();
while (resources.hasNext()) {
IProject currentResource = (IProject) resources.next();
if (!currentResource.isOpen()) {
return true;
}
}
return false;
}
}