/******************************************************************************* * 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 * Alex Collins (Broadcom Corp.) *******************************************************************************/ package org.eclipse.cdt.internal.ui.cview; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.core.resources.ICommand; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.IShellProvider; import org.eclipse.swt.events.KeyEvent; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.BuildAction; import org.eclipse.ui.ide.IDEActionFactory; import org.eclipse.ui.ide.ResourceUtil; import org.eclipse.cdt.ui.CUIPlugin; /** * This is the action group for workspace actions such as Build */ public class BuildGroup extends CViewActionGroup { /** * An internal class which overrides the 'shouldPerformResourcePruning' * method so that referenced projects aren't build twice . (The CDT * managedbuild builds CDT reference project configuration as part of * building the top-level project). * * Also ensure that files in referenced projects are saved automatically * before build. */ public static class CDTBuildAction extends BuildAction { public CDTBuildAction(IShellProvider shell, int kind) { super(shell, kind); } @Override @SuppressWarnings("unchecked") public void run() { // Ensure we correctly save files in all referenced projects before build Set<IProject> prjs = new HashSet<IProject>(); for (IResource resource : (List<IResource>)getSelectedResources()) { IProject project = resource.getProject(); if (project != null) { prjs.add(project); try { prjs.addAll(Arrays.asList(project.getReferencedProjects())); } catch (CoreException e) { // Project not accessible or not open } } } saveEditors(prjs); // Clear the build console, and open a stream CUIPlugin.getDefault().startGlobalConsole(); // Now delegate to the parent super.run(); } /** * Taken from inaccessible o.e.ui.ide.BuildUtilities.java * * Causes all editors to save any modified resources in the provided collection * of projects depending on the user's preference. * @param projects The projects in which to save editors, or <code>null</code> * to save editors in all projects. */ private static void saveEditors(Collection<IProject> projects) { if (!BuildAction.isSaveAllSet()) { return; } IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows(); for (IWorkbenchWindow window : windows) { IWorkbenchPage[] pages = window.getPages(); for (IWorkbenchPage page : pages) { if (projects == null) { page.saveAllEditors(false); } else { IEditorPart[] editors = page.getDirtyEditors(); for (IEditorPart editor : editors) { IFile inputFile = ResourceUtil.getFile(editor.getEditorInput()); if (inputFile != null) { if (projects.contains(inputFile.getProject())) { page.saveEditor(editor, false); } } } } } } } } private static class RebuildAction extends CDTBuildAction { public RebuildAction(IShellProvider shell) { super(shell, IncrementalProjectBuilder.FULL_BUILD); } @Override protected void invokeOperation(IResource resource, IProgressMonitor monitor) throws CoreException { // these are both async. NOT what I want. ((IProject) resource).build(IncrementalProjectBuilder.CLEAN_BUILD, monitor); ((IProject) resource).build(IncrementalProjectBuilder.FULL_BUILD, monitor); } } private BuildAction buildAction; private BuildAction rebuildAction; private BuildAction cleanAction; // Menu tags for the build final String BUILD_GROUP_MARKER = "buildGroup"; //$NON-NLS-1$ final String BUILD_GROUP_MARKER_END = "end-buildGroup"; //$NON-NLS-1$ public BuildGroup(CView cview) { super(cview); } @Override public void fillActionBars(IActionBars actionBars) { actionBars.setGlobalActionHandler(IDEActionFactory.BUILD_PROJECT.getId(), buildAction); } /** * Adds the build actions to the context menu. * <p> * The following conditions apply: build-only projects selected, auto build * disabled, at least one * builder present * </p> * <p> * No disabled action should be on the context menu. * </p> * * @param menu * context menu to add actions to */ @Override public void fillContextMenu(IMenuManager menu) { IStructuredSelection selection = (IStructuredSelection) getContext().getSelection(); boolean isProjectSelection = true; boolean hasOpenProjects = false; boolean hasClosedProjects = false; boolean hasBuilder = true; // false if any project is closed or does // not have builder menu.add(new GroupMarker(BUILD_GROUP_MARKER)); Iterator<?> resources = selection.iterator(); while (resources.hasNext() && (!hasOpenProjects || !hasClosedProjects || hasBuilder || isProjectSelection)) { Object next = resources.next(); IProject project = null; if (next instanceof IProject) { project = (IProject) next; } else if (next instanceof IAdaptable) { IResource res = (IResource)((IAdaptable)next).getAdapter(IResource.class); if (res instanceof IProject) { project = (IProject) res; } } if (project == null) { isProjectSelection = false; continue; } if (project.isOpen()) { hasOpenProjects = true; if (hasBuilder && !hasBuilder(project)) { hasBuilder = false; } } else { hasClosedProjects = true; hasBuilder = false; } } if (!selection.isEmpty() && isProjectSelection && hasBuilder) { buildAction.selectionChanged(selection); menu.add(buildAction); // rebuildAction.selectionChanged(selection); // menu.add(rebuildAction); cleanAction.selectionChanged(selection); menu.add(cleanAction); } menu.add(new GroupMarker(BUILD_GROUP_MARKER_END)); } /** * Handles a key pressed event by invoking the appropriate action. */ @Override public void handleKeyPressed(KeyEvent event) { } /** * Returns whether there are builders configured on the given project. * * @return <code>true</code> if it has builders, <code>false</code> if * not, or if this could not be determined */ boolean hasBuilder(IProject project) { try { ICommand[] commands = project.getDescription().getBuildSpec(); if (commands.length > 0) return true; } catch (CoreException e) { // Cannot determine if project has builders. Project is closed // or does not exist. Fall through to return false. } return false; } @Override protected void makeActions() { final IWorkbenchPartSite site = getCView().getSite(); buildAction = new CDTBuildAction(site, IncrementalProjectBuilder.INCREMENTAL_BUILD); buildAction.setText(CViewMessages.BuildAction_label); cleanAction = new CDTBuildAction(site, IncrementalProjectBuilder.CLEAN_BUILD); cleanAction.setText(CViewMessages.CleanAction_label); rebuildAction = new RebuildAction(site); rebuildAction.setText(CViewMessages.RebuildAction_label); } @Override public void updateActionBars() { IStructuredSelection selection = (IStructuredSelection) getContext().getSelection(); buildAction.selectionChanged(selection); } }