org.eclipse.ui.actions.OpenResourceAction.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ui.actions.OpenResourceAction.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2010 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.openYesNoQuestion(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;
            private boolean canceled = 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() {
                                try {
                                    openProjectReferences = promptToOpenWithReferences();
                                } catch (OperationCanceledException e) {
                                    canceled = true;
                                }
                                //remember that we have prompted to avoid repeating the analysis
                                hasPrompted = true;
                            }
                        });
                        if (canceled)
                            throw new OperationCanceledException();
                    }
                }
                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;
    }
}