/*******************************************************************************
* Copyright (c) 2000, 2012 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
*******************************************************************************/
package org.eclipse.debug.ui.actions;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.IEvaluationContext;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchMode;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.actions.ActionMessages;
import org.eclipse.debug.internal.ui.actions.LaunchConfigurationAction;
import org.eclipse.debug.internal.ui.actions.LaunchShortcutAction;
import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationManager;
import org.eclipse.debug.internal.ui.launchConfigurations.LaunchShortcutExtension;
import org.eclipse.debug.internal.ui.stringsubstitution.SelectedResourceManager;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.ILaunchGroup;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkbenchWindowPulldownDelegate2;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.activities.WorkbenchActivityHelper;
/**
* A cascading sub-menu that shows all launch shortcuts pertinent to a
* selection. This action is similar to ContextualLaunchAction
* except this action is an IAction
rather than an action
* delegate.
*
* This action appears in the main Run menu *
** Clients may subclass this class. *
* @since 3.1 */ public class LaunchShortcutsAction extends Action implements IMenuCreator, IWorkbenchWindowPulldownDelegate2 { /** * Cascading menu */ private Menu fCreatedMenu; /** * Launch group */ private ILaunchGroup fGroup; /** * Whether this actions enablement has been initialized */ private boolean fInitialized = false; /** * Creates a cascading menu action to populate with shortcuts in the given * launch group. * * @param launchGroupIdentifier launch group identifier */ public LaunchShortcutsAction(String launchGroupIdentifier) { super(); fGroup = DebugUIPlugin.getDefault().getLaunchConfigurationManager().getLaunchGroup(launchGroupIdentifier); ILaunchMode mode = DebugPlugin.getDefault().getLaunchManager().getLaunchMode(fGroup.getMode()); setText(mode.getLaunchAsLabel()); setMenuCreator(this); setEnabled(existsConfigTypesForMode()); } /** * @see IAction#run() */ public void run() { //do nothing, this action just creates a cascading menu. } /** * @see IMenuCreator#dispose() */ public void dispose() { if (fCreatedMenu != null) { fCreatedMenu.dispose(); } } /** * @see IMenuCreator#getMenu(Control) */ public Menu getMenu(Control parent) { return null; } /** * @see IMenuCreator#getMenu(Menu) */ public Menu getMenu(Menu parent) { if (fCreatedMenu != null) { fCreatedMenu.dispose(); } fCreatedMenu = new Menu(parent); initMenu(); return fCreatedMenu; } /** * @return an Evaluation context with default variable = selection */ private IEvaluationContext createContext() { IStructuredSelection ss = SelectedResourceManager.getDefault().getCurrentSelection(); Object o = ss.getFirstElement(); List list = new ArrayList(0); if(o instanceof IEditorPart) { list.add(((IEditorPart)o).getEditorInput()); } else { list.addAll(ss.toList()); } IEvaluationContext context = DebugUIPlugin.createEvaluationContext(list); context.setAllowPluginActivation(true); context.addVariable("selection", list); //$NON-NLS-1$ return context; } /** * Fills the fly-out menu */ private void fillMenu() { IEvaluationContext context = createContext(); int accelerator = 1; List allShortCuts = getLaunchConfigurationManager().getLaunchShortcuts(fGroup.getCategory()); Iterator iter = allShortCuts.iterator(); List filteredShortCuts = new ArrayList(10); while (iter.hasNext()) { LaunchShortcutExtension ext = (LaunchShortcutExtension) iter.next(); try { if (!WorkbenchActivityHelper.filterItem(ext) && isApplicable(ext, context)) { filteredShortCuts.add(ext); } } catch (CoreException e) { IStatus status = new Status(IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(), "Launch shortcut '" + ext.getId() + "' enablement expression caused exception. Shortcut was removed.", e); //$NON-NLS-1$ //$NON-NLS-2$ DebugUIPlugin.log(status); iter.remove(); } } //first add the launch config if it is one String mode = getMode(); try { ILaunchConfiguration config = getLaunchConfigurationManager().isSharedConfig(getSelection(context)); if(config != null && config.exists() && config.supportsMode(mode)) { IAction action = new LaunchConfigurationAction(config, mode, config.getName(), DebugUITools.getDefaultImageDescriptor(config), accelerator++); ActionContributionItem item = new ActionContributionItem(action); item.fill(fCreatedMenu, -1); if(!filteredShortCuts.isEmpty()) { new MenuItem(fCreatedMenu, SWT.SEPARATOR); } } } catch(CoreException ce) {DebugUIPlugin.log(ce);} //second add the launch shortcuts if any iter = filteredShortCuts.iterator(); while (iter.hasNext()) { LaunchShortcutExtension ext = (LaunchShortcutExtension) iter.next(); Set modes = ext.getModes(); // supported launch modes Iterator modeIter = modes.iterator(); while (modeIter.hasNext()) { String modee = (String) modeIter.next(); if (modee.equals(mode)) { populateMenuItem(modee, ext, fCreatedMenu, accelerator++); } } } if (accelerator == 1) { // No shortcuts added. Add "none available" action. IAction action= new Action(ActionMessages.LaunchShortcutsAction_1) {}; action.setEnabled(false); ActionContributionItem item= new ActionContributionItem(action); item.fill(fCreatedMenu, -1); } } /** * Returns the first element of the current selection * @param context the current evaluation context * @return the first item in the selection, ornull
if none
* @since 3.3
*/
private Object getSelection(IEvaluationContext context) {
List list = (List) context.getVariable("selection"); //$NON-NLS-1$
return (list.isEmpty() ? null : list.get(0));
}
/**
* Add the shortcut to the context menu's launch sub-menu.
* @param mode the launch mode identifier
* @param ext the shortcut extension to get label and help information from
* @param menu the menu to add to
* @param accelerator the accelerator to use
*/
private void populateMenuItem(String mode, LaunchShortcutExtension ext, Menu menu, int accelerator) {
LaunchShortcutAction action = new LaunchShortcutAction(mode, ext);
action.setActionDefinitionId(ext.getId() + "." + mode); //$NON-NLS-1$
String helpContextId = ext.getHelpContextId();
if (helpContextId != null) {
PlatformUI.getWorkbench().getHelpSystem().setHelp(action, helpContextId);
}
StringBuffer label= new StringBuffer();
if (accelerator >= 0 && accelerator < 10) {
//add the numerical accelerator
label.append('&');
label.append(accelerator);
label.append(' ');
}
String contextLabel= ext.getContextLabel(mode);
// replace default action label with context label if specified.
label.append((contextLabel != null) ? contextLabel : action.getText());
action.setText(label.toString());
ActionContributionItem item= new ActionContributionItem(action);
item.fill(menu, -1);
}
/**
* Evaluate the enablement logic in the contextualLaunch
* element description. A true result means that we should
* include this shortcut in the context menu.
* @param ext the launch shortcut extension to get the enablement expression from
* @param context the context to use for enablement evaluation
* @return true iff shortcut should appear in context menu
* @throws CoreException if an exception occurs
*/
private boolean isApplicable(LaunchShortcutExtension ext, IEvaluationContext context) throws CoreException {
Expression expr = ext.getContextualLaunchEnablementExpression();
return ext.evalEnablementExpression(context, expr);
}
/**
* Creates the menu for the action
*/
private void initMenu() {
// Add listener to re-populate the menu each time
// it is shown to reflect changes in selection or active perspective
fCreatedMenu.addMenuListener(new MenuAdapter() {
public void menuShown(MenuEvent e) {
Menu m = (Menu)e.widget;
MenuItem[] items = m.getItems();
for (int i=0; i < items.length; i++) {
items[i].dispose();
}
fillMenu();
}
});
}
/**
* Returns the mode of this action - run or debug
*
* @return the mode of this action - run or debug
*/
protected String getMode() {
return fGroup.getMode();
}
/**
* Returns the launch configuration manager.
*
* @return launch configuration manager
*/
private LaunchConfigurationManager getLaunchConfigurationManager() {
return DebugUIPlugin.getDefault().getLaunchConfigurationManager();
}
/**
* @see org.eclipse.ui.IWorkbenchWindowActionDelegate#init(org.eclipse.ui.IWorkbenchWindow)
*/
public void init(IWorkbenchWindow window) {}
/**
* @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
*/
public void run(IAction action) {
// do nothing - this is just a menu
}
/**
* @see org.eclipse.ui.IActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
*/
public void selectionChanged(IAction action, ISelection selection) {
if (!fInitialized) {
action.setEnabled(existsConfigTypesForMode());
fInitialized = true;
}
}
/**
* Return whether there are any registered launch configuration types for
* the mode of this action.
*
* @return whether there are any registered launch configuration types for
* the mode of this action
*/
private boolean existsConfigTypesForMode() {
ILaunchConfigurationType[] configTypes = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationTypes();
for (int i = 0; i < configTypes.length; i++) {
ILaunchConfigurationType configType = configTypes[i];
if (configType.supportsMode(getMode())) {
return true;
}
}
return false;
}
}