Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Duft2016-05-11 13:52:28 +0000
committerMarkus Duft2016-11-30 09:42:25 +0000
commit97be8772a897b47a48b2d4b6ef33b46811408b7f (patch)
treeef2793a75f11741be425b7d236695df5f0f252d2 /org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui
parent66da2950cc347953d38ae225f82b5f23f5e960e7 (diff)
downloadeclipse.platform.debug-97be8772a897b47a48b2d4b6ef33b46811408b7f.tar.gz
eclipse.platform.debug-97be8772a897b47a48b2d4b6ef33b46811408b7f.tar.xz
eclipse.platform.debug-97be8772a897b47a48b2d4b6ef33b46811408b7f.zip
Initial contribution of Launch Groups
The initial contribution is a slightly modified/polished version of the launch group code in org.eclipse.cdt.launch. A follow up commit will contain additional modifications to merge features from another (external) implementation of launch groups. Bug: 492788 Change-Id: Ie0a902b857a5c2cc02f5c36d8591001493bd6e19 Signed-off-by: Markus Duft <markus.duft@ssi-schaefer.com>
Diffstat (limited to 'org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui')
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.java31
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.properties32
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/ComboControlledStackComposite.java138
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/CommonTabLite.java603
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupCycleHandler.java39
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupElementLaunchedHandler.java41
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationSelectionDialog.java399
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationTabGroup.java572
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchHandler.java65
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/UnsupportedModeHandler.java43
10 files changed, 1963 insertions, 0 deletions
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.java
index be895c0d4..93095e320 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.java
@@ -237,6 +237,37 @@ public class DebugUIMessages extends NLS {
public static String GoToAddressComposite_7;
//
+ // Launch Groups
+ //
+ public static String GroupLaunch_Cannot_launch;
+ public static String GroupLaunch_Cycle;
+ public static String GroupLaunch_Error;
+ public static String GroupLaunchConfigurationSelectionDialog_10;
+ public static String GroupLaunchConfigurationSelectionDialog_11;
+ public static String GroupLaunchConfigurationSelectionDialog_12;
+ public static String GroupLaunchConfigurationSelectionDialog_13;
+ public static String GroupLaunchConfigurationSelectionDialog_14;
+ public static String GroupLaunchConfigurationSelectionDialog_15;
+ public static String GroupLaunchConfigurationSelectionDialog_4;
+ public static String GroupLaunchConfigurationSelectionDialog_5;
+ public static String GroupLaunchConfigurationSelectionDialog_7;
+ public static String GroupLaunchConfigurationSelectionDialog_8;
+ public static String GroupLaunchConfigurationSelectionDialog_9;
+ public static String GroupLaunchConfigurationTabGroup_1;
+ public static String GroupLaunchConfigurationTabGroup_10;
+ public static String GroupLaunchConfigurationTabGroup_12;
+ public static String GroupLaunchConfigurationTabGroup_13;
+ public static String GroupLaunchConfigurationTabGroup_14;
+ public static String GroupLaunchConfigurationTabGroup_15;
+ public static String GroupLaunchConfigurationTabGroup_16;
+ public static String GroupLaunchConfigurationTabGroup_2;
+ public static String GroupLaunchConfigurationTabGroup_3;
+ public static String GroupLaunchConfigurationTabGroup_4;
+ public static String GroupLaunchConfigurationTabGroup_5;
+ public static String GroupLaunchConfigurationTabGroup_6;
+ public static String GroupLaunchConfigurationTabGroup_7;
+
+ //
// Blocks
//
public static String WorkingDirectoryBlock_4;
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.properties b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.properties
index 8cc9fc674..04df7fa8d 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.properties
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.properties
@@ -109,6 +109,38 @@ MonitorMemoryBlockDialog_MonitorMemory = Monitor Memory
MonitorMemoryBlockDialog_NumberOfBytes = Number of bytes:
GoToAddressDialog_Address = Address:
GoToAddressDialog_GoToAddress = Go To Address...
+
+##############################################################
+# Launch Groups
+##############################################################
+GroupLaunch_Cannot_launch=Cannot launch ''{0}'' in the ''{1}'' mode
+GroupLaunch_Cycle=Infinite loop detected for ''{0}'' group
+GroupLaunch_Error=Error
+GroupLaunchConfigurationSelectionDialog_4=Launch Mode:
+GroupLaunchConfigurationSelectionDialog_5=Use default mode when launching
+GroupLaunchConfigurationSelectionDialog_7=Select a launch configuration
+GroupLaunchConfigurationSelectionDialog_8=Post launch action:
+GroupLaunchConfigurationSelectionDialog_9=Seconds:
+GroupLaunchConfigurationSelectionDialog_10=Enter valid number of seconds
+GroupLaunchConfigurationSelectionDialog_11=Select only one launch configuration
+GroupLaunchConfigurationSelectionDialog_12=Add Launch Configuration
+GroupLaunchConfigurationSelectionDialog_13=Edit Launch Configuration
+GroupLaunchConfigurationSelectionDialog_14=Add one or more launch configurations to the launch group
+GroupLaunchConfigurationSelectionDialog_15=Edit an existing entry in the launch group
+GroupLaunchConfigurationTabGroup_1=Up
+GroupLaunchConfigurationTabGroup_2=Down
+GroupLaunchConfigurationTabGroup_3=Edit...
+GroupLaunchConfigurationTabGroup_4=Add...
+GroupLaunchConfigurationTabGroup_5=Remove
+GroupLaunchConfigurationTabGroup_6=Name
+GroupLaunchConfigurationTabGroup_7=Mode
+GroupLaunchConfigurationTabGroup_10=Launches
+GroupLaunchConfigurationTabGroup_12=Action
+GroupLaunchConfigurationTabGroup_13=Delay {0} seconds
+GroupLaunchConfigurationTabGroup_14=Launch {0} does not exist.
+GroupLaunchConfigurationTabGroup_15=Launch {0} is filtered.
+GroupLaunchConfigurationTabGroup_16=Must have at least one valid enabled launch.
+
CodePagesPrefDialog_1=Select Codepages
CodePagesPrefDialog_2=Memory to ASCII strings:
CodePagesPrefDialog_4=Memory to EBCDIC strings:
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/ComboControlledStackComposite.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/ComboControlledStackComposite.java
new file mode 100644
index 000000000..fed29d2dc
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/ComboControlledStackComposite.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2016 QNX Software Systems 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:
+ * QNX Software Systems - initial API and implementation
+ * Freescale Semiconductor
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.groups;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+/**
+ * Stack Composite - Switch between panes controlled by combo box
+ * <p>
+ * Copied from CDT (org.eclipse.cdt.launch)
+ */
+class ComboControlledStackComposite extends Composite {
+ private Composite fArea;
+ private Combo fCombo;
+ private Map<String, Composite> tabMap; // label ==> tab
+ private StackLayout layout;
+ private Label fLabel;
+
+ public ComboControlledStackComposite(Composite parent, int style) {
+ super(parent, style);
+ tabMap = new LinkedHashMap<String, Composite>();
+ setLayout(new GridLayout(2, false));
+ createContents(this);
+ }
+
+ public void setLabelText(String label) {
+ fLabel.setText(label);
+ }
+ public void addItem(String label, Composite tab) {
+ tabMap.put(label, tab);
+ fCombo.add(label);
+ if (layout.topControl==null) {
+ layout.topControl = tab;
+ fCombo.setText(label);
+ }
+ }
+
+ public void deleteItem(String label) {
+ if (fCombo.getText().equals(label)) {
+ setSelection(fCombo.getItem(0));
+ }
+ Composite tab = tabMap.get(label);
+ if (tab != null) {
+ tab.dispose();
+ tabMap.remove(label);
+ }
+ }
+
+ public void setSelection(String label) {
+ fCombo.setText(label);
+ setPage(label);
+ }
+
+ protected void createContents(Composite parent) {
+ fLabel = createLabel(this);
+ fCombo = createCombo(this);
+ GridData cgd = new GridData(GridData.FILL_HORIZONTAL);
+
+ fCombo.setLayoutData(cgd);
+ fArea = createTabArea(this);
+ GridData agd = new GridData(GridData.FILL_BOTH);
+ agd.horizontalSpan = 2;
+ fArea.setLayoutData(agd);
+ }
+
+
+ public Composite getStackParent() {
+ return fArea;
+ }
+
+ public Label getLabel() {
+ return fLabel;
+ }
+
+ public Combo getCombo() {
+ return fCombo;
+ }
+
+ protected Composite createTabArea(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE);
+ layout = new StackLayout();
+ comp.setLayout(layout);
+
+ return comp;
+ }
+
+
+ protected Label createLabel(Composite parent) {
+ Label label = new Label(parent, SWT.WRAP);
+ return label;
+ }
+
+ protected Combo createCombo(Composite parent) {
+ Combo box = new Combo(parent, SWT.READ_ONLY);
+ box.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ String name = fCombo.getText();
+ comboSelected(name);
+ }
+ });
+ return box;
+ }
+
+ protected void comboSelected(String label) {
+ setPage(label);
+ }
+
+ protected void setPage(String label) {
+ layout.topControl = tabMap.get(label);
+ getStackParent().layout();
+ }
+
+ public Control getTopControl() {
+ return layout != null ? layout.topControl : null;
+ }
+}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/CommonTabLite.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/CommonTabLite.java
new file mode 100644
index 000000000..4261844f4
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/CommonTabLite.java
@@ -0,0 +1,603 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2012, 2016 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
+ * Freescale Semiconductor (stripped out functionality from platform debug version)
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.groups;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
+import org.eclipse.debug.internal.ui.DebugUIPlugin;
+import org.eclipse.debug.internal.ui.IDebugHelpContextIds;
+import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
+import org.eclipse.debug.internal.ui.SWTFactory;
+import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationManager;
+import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsMessages;
+import org.eclipse.debug.internal.ui.launchConfigurations.LaunchGroupExtension;
+import org.eclipse.debug.internal.ui.launchConfigurations.LaunchHistory;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.ILaunchGroup;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.ContainerSelectionDialog;
+
+/**
+ * This class was taken from org.eclipse.debug.ui. We expose a Common tab for
+ * Multilaunch that has only a subset of the standard tab's properties.
+ *
+ * Launch configuration tab used to specify the location a launch configuration
+ * is stored in, whether it should appear in the favorites list, and perspective
+ * switching behavior for an associated launch.
+ * <p>
+ * Clients may instantiate this class.
+ * <p>
+ * Copied from CDT (org.eclipse.cdt.launch)
+ */
+class CommonTabLite extends AbstractLaunchConfigurationTab {
+
+ /**
+ * Provides a persistible dialog for selecting the shared project location
+ * @since 3.2
+ */
+ class SharedLocationSelectionDialog extends ContainerSelectionDialog {
+ private final String SETTINGS_ID = IDebugUIConstants.PLUGIN_ID + ".SHARED_LAUNCH_CONFIGURATON_DIALOG"; //$NON-NLS-1$
+
+ public SharedLocationSelectionDialog(Shell parentShell, IContainer initialRoot, boolean allowNewContainerName, String message) {
+ super(parentShell, initialRoot, allowNewContainerName, message);
+ }
+
+ @Override
+ protected IDialogSettings getDialogBoundsSettings() {
+ IDialogSettings settings = DebugUIPlugin.getDefault().getDialogSettings();
+ IDialogSettings section = settings.getSection(SETTINGS_ID);
+ if (section == null) {
+ section = settings.addNewSection(SETTINGS_ID);
+ }
+ return section;
+ }
+ }
+
+ /**
+ * This attribute exists solely for the purpose of making sure that invalid shared locations
+ * can be revertible. This attribute is not saveable and will never appear in a saved
+ * launch configuration.
+ * @since 3.3
+ */
+ private static final String BAD_CONTAINER = "bad_container_name"; //$NON-NLS-1$
+
+ // Local/shared UI widgets
+ private Button fLocalRadioButton;
+ private Button fSharedRadioButton;
+ private Text fSharedLocationText;
+ private Button fSharedLocationButton;
+
+ /**
+ * Check box list for specifying favorites
+ */
+ private CheckboxTableViewer fFavoritesTable;
+
+ /**
+ * Modify listener that simply updates the owning launch configuration dialog.
+ */
+ private ModifyListener fBasicModifyListener = new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent evt) {
+ updateLaunchConfigurationDialog();
+ }
+ };
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
+ */
+ @Override
+ public void createControl(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE);
+ setControl(comp);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IDebugHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_COMMON_TAB);
+ comp.setLayout(new GridLayout(2, true));
+ comp.setFont(parent.getFont());
+
+ createSharedConfigComponent(comp);
+ createFavoritesComponent(comp);
+ }
+
+ /**
+ * Creates the favorites control
+ * @param parent the parent composite to add this one to
+ * @since 3.2
+ */
+ private void createFavoritesComponent(Composite parent) {
+ Group favComp = SWTFactory.createGroup(parent, LaunchConfigurationsMessages.CommonTab_Display_in_favorites_menu__10, 1, 1, GridData.FILL_BOTH);
+ fFavoritesTable = CheckboxTableViewer.newCheckList(favComp, SWT.CHECK | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);
+ Control table = fFavoritesTable.getControl();
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ table.setLayoutData(gd);
+ table.setFont(parent.getFont());
+ fFavoritesTable.setContentProvider(new FavoritesContentProvider());
+ fFavoritesTable.setLabelProvider(new FavoritesLabelProvider());
+ fFavoritesTable.addCheckStateListener(new ICheckStateListener() {
+ @Override
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ updateLaunchConfigurationDialog();
+ }
+ });
+ }
+
+ /**
+ * Creates the shared config component
+ * @param parent the parent composite to add this component to
+ * @since 3.2
+ */
+ private void createSharedConfigComponent(Composite parent) {
+ Group group = SWTFactory.createGroup(parent, LaunchConfigurationsMessages.CommonTab_0, 3, 2, GridData.FILL_HORIZONTAL);
+ Composite comp = SWTFactory.createComposite(group, parent.getFont(), 3, 3, GridData.FILL_BOTH, 0, 0);
+ fLocalRadioButton = createRadioButton(comp, LaunchConfigurationsMessages.CommonTab_L_ocal_3);
+ GridData gd = new GridData();
+ gd.horizontalSpan = 3;
+ fLocalRadioButton.setLayoutData(gd);
+ fSharedRadioButton = createRadioButton(comp, LaunchConfigurationsMessages.CommonTab_S_hared_4);
+ fSharedRadioButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent evt) {
+ handleSharedRadioButtonSelected();
+ }
+ });
+ fSharedLocationText = SWTFactory.createSingleText(comp, 1);
+ fSharedLocationText.getAccessible().addAccessibleListener(new AccessibleAdapter() {
+ @Override
+ public void getName(AccessibleEvent e) {
+ e.result = LaunchConfigurationsMessages.CommonTab_S_hared_4;
+ }
+ });
+ fSharedLocationText.addModifyListener(fBasicModifyListener);
+ fSharedLocationButton = createPushButton(comp, LaunchConfigurationsMessages.CommonTab__Browse_6, null);
+ fSharedLocationButton.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent evt) {
+ handleSharedLocationButtonSelected();
+ }
+ });
+
+ fLocalRadioButton.setSelection(true);
+ setSharedEnabled(false);
+ }
+
+ /**
+ * handles the shared radio button being selected
+ */
+ private void handleSharedRadioButtonSelected() {
+ setSharedEnabled(isShared());
+ updateLaunchConfigurationDialog();
+ }
+
+ /**
+ * Sets the widgets for specifying that a launch configuration is to be shared to the enable value
+ * @param enable the enabled value for
+ */
+ private void setSharedEnabled(boolean enable) {
+ fSharedLocationText.setEnabled(enable);
+ fSharedLocationButton.setEnabled(enable);
+ }
+
+ private String getDefaultSharedConfigLocation(ILaunchConfiguration config) {
+ String path = IInternalDebugCoreConstants.EMPTY_STRING;
+ try {
+ IResource[] res = config.getMappedResources();
+ if(res != null) {
+ IProject proj;
+ for (int i = 0; i < res.length; i++) {
+ proj = res[i].getProject();
+ if(proj != null && proj.isAccessible()) {
+ return proj.getFullPath().toOSString();
+ }
+ }
+ }
+ }
+ catch (CoreException e) {DebugUIPlugin.log(e);}
+ return path;
+ }
+
+ /**
+ * if the shared radio button is selected, indicating that the launch configuration is to be shared
+ * @return true if the radio button is selected, false otherwise
+ */
+ private boolean isShared() {
+ return fSharedRadioButton.getSelection();
+ }
+
+ /**
+ * Handles the shared location button being selected
+ */
+ private void handleSharedLocationButtonSelected() {
+ String currentContainerString = fSharedLocationText.getText();
+ IContainer currentContainer = getContainer(currentContainerString);
+ SharedLocationSelectionDialog dialog = new SharedLocationSelectionDialog(getShell(),
+ currentContainer,
+ false,
+ LaunchConfigurationsMessages.CommonTab_Select_a_location_for_the_launch_configuration_13);
+ dialog.showClosedProjects(false);
+ dialog.open();
+ Object[] results = dialog.getResult();
+ if ((results != null) && (results.length > 0) && (results[0] instanceof IPath)) {
+ IPath path = (IPath)results[0];
+ String containerName = path.toOSString();
+ fSharedLocationText.setText(containerName);
+ }
+ }
+
+ /**
+ * gets the container form the specified path
+ * @param path the path to get the container from
+ * @return the container for the specified path or null if one cannot be determined
+ */
+ private IContainer getContainer(String path) {
+ Path containerPath = new Path(path);
+ return (IContainer) getWorkspaceRoot().findMember(containerPath);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ @Override
+ public void initializeFrom(ILaunchConfiguration configuration) {
+ boolean isShared = !configuration.isLocal();
+ fSharedRadioButton.setSelection(isShared);
+ fLocalRadioButton.setSelection(!isShared);
+ setSharedEnabled(isShared);
+ fSharedLocationText.setText(getDefaultSharedConfigLocation(configuration));
+ if(isShared) {
+ String containerName = IInternalDebugCoreConstants.EMPTY_STRING;
+ IFile file = configuration.getFile();
+ if (file != null) {
+ IContainer parent = file.getParent();
+ if (parent != null) {
+ containerName = parent.getFullPath().toOSString();
+ }
+ }
+ fSharedLocationText.setText(containerName);
+ }
+ updateFavoritesFromConfig(configuration);
+ }
+
+
+ /**
+ * Updates the favorites selections from the local configuration
+ * @param config the local configuration
+ */
+ private void updateFavoritesFromConfig(ILaunchConfiguration config) {
+ fFavoritesTable.setInput(config);
+ fFavoritesTable.setCheckedElements(new Object[]{});
+ try {
+ List groups = config.getAttribute(IDebugUIConstants.ATTR_FAVORITE_GROUPS, new ArrayList());
+ if (groups.isEmpty()) {
+ // check old attributes for backwards compatible
+ if (config.getAttribute(IDebugUIConstants.ATTR_DEBUG_FAVORITE, false)) {
+ groups.add(IDebugUIConstants.ID_DEBUG_LAUNCH_GROUP);
+ }
+ if (config.getAttribute(IDebugUIConstants.ATTR_RUN_FAVORITE, false)) {
+ groups.add(IDebugUIConstants.ID_RUN_LAUNCH_GROUP);
+ }
+ }
+ if (!groups.isEmpty()) {
+ List list = new ArrayList();
+ Iterator iterator = groups.iterator();
+ while (iterator.hasNext()) {
+ String id = (String)iterator.next();
+ LaunchGroupExtension extension = getLaunchConfigurationManager().getLaunchGroup(id);
+ if (extension != null) {
+ list.add(extension);
+ }
+ }
+ fFavoritesTable.setCheckedElements(list.toArray());
+ }
+ } catch (CoreException e) {
+ DebugUIPlugin.log(e);
+ }
+ }
+
+ /**
+ * Updates the configuration form the local shared config working copy
+ * @param config the local shared config working copy
+ */
+ private void updateConfigFromLocalShared(ILaunchConfigurationWorkingCopy config) {
+ if (isShared()) {
+ String containerPathString = fSharedLocationText.getText();
+ IContainer container = getContainer(containerPathString);
+ if(container == null) {
+ //we need to force an attribute to allow the invalid container path to be revertable
+ config.setAttribute(BAD_CONTAINER, containerPathString);
+ }
+ else {
+ config.setContainer(container);
+ }
+ } else {
+ config.setContainer(null);
+ }
+ }
+
+ /**
+ * Convenience accessor
+ */
+ protected LaunchConfigurationManager getLaunchConfigurationManager() {
+ return DebugUIPlugin.getDefault().getLaunchConfigurationManager();
+ }
+
+ /**
+ * Update the favorite settings.
+ *
+ * NOTE: set to <code>null</code> instead of <code>false</code> for backwards compatibility
+ * when comparing if content is equal, since 'false' is default
+ * and will be missing for older configurations.
+ */
+ private void updateConfigFromFavorites(ILaunchConfigurationWorkingCopy config) {
+ try {
+ Object[] checked = fFavoritesTable.getCheckedElements();
+ boolean debug = config.getAttribute(IDebugUIConstants.ATTR_DEBUG_FAVORITE, false);
+ boolean run = config.getAttribute(IDebugUIConstants.ATTR_RUN_FAVORITE, false);
+ if (debug || run) {
+ // old attributes
+ List groups = new ArrayList();
+ int num = 0;
+ if (debug) {
+ groups.add(getLaunchConfigurationManager().getLaunchGroup(IDebugUIConstants.ID_DEBUG_LAUNCH_GROUP));
+ num++;
+ }
+ if (run) {
+ num++;
+ groups.add(getLaunchConfigurationManager().getLaunchGroup(IDebugUIConstants.ID_RUN_LAUNCH_GROUP));
+ }
+ // see if there are any changes
+ if (num == checked.length) {
+ boolean different = false;
+ for (int i = 0; i < checked.length; i++) {
+ if (!groups.contains(checked[i])) {
+ different = true;
+ break;
+ }
+ }
+ if (!different) {
+ return;
+ }
+ }
+ }
+ config.setAttribute(IDebugUIConstants.ATTR_DEBUG_FAVORITE, (String)null);
+ config.setAttribute(IDebugUIConstants.ATTR_RUN_FAVORITE, (String)null);
+ List groups = null;
+ for (int i = 0; i < checked.length; i++) {
+ LaunchGroupExtension group = (LaunchGroupExtension)checked[i];
+ if (groups == null) {
+ groups = new ArrayList();
+ }
+ groups.add(group.getIdentifier());
+ }
+ config.setAttribute(IDebugUIConstants.ATTR_FAVORITE_GROUPS, groups);
+ } catch (CoreException e) {
+ DebugUIPlugin.log(e);
+ }
+ }
+
+ /**
+ * Convenience method for getting the workspace root.
+ */
+ private IWorkspaceRoot getWorkspaceRoot() {
+ return ResourcesPlugin.getWorkspace().getRoot();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ @Override
+ public boolean isValid(ILaunchConfiguration config) {
+ setMessage(null);
+ setErrorMessage(null);
+
+ return validateLocalShared();
+ }
+
+ /**
+ * validates the local shared config file location
+ * @return true if the local shared file exists, false otherwise
+ */
+ private boolean validateLocalShared() {
+ if (isShared()) {
+ String path = fSharedLocationText.getText().trim();
+ IContainer container = getContainer(path);
+ if (container == null || container.equals(ResourcesPlugin.getWorkspace().getRoot())) {
+ setErrorMessage(LaunchConfigurationsMessages.CommonTab_Invalid_shared_configuration_location_14);
+ return false;
+ } else if (!container.getProject().isOpen()) {
+ setErrorMessage(LaunchConfigurationsMessages.CommonTab_Cannot_save_launch_configuration_in_a_closed_project__1);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ @Override
+ public void setDefaults(ILaunchConfigurationWorkingCopy config) {
+ config.setContainer(null);
+ setAttribute(IDebugUIConstants.ATTR_LAUNCH_IN_BACKGROUND, config, true, true);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ @Override
+ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ updateConfigFromLocalShared(configuration);
+ updateConfigFromFavorites(configuration);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
+ */
+ @Override
+ public String getName() {
+ return LaunchConfigurationsMessages.CommonTab__Common_15;
+ }
+
+ /**
+ * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getId()
+ *
+ * @since 3.3
+ */
+ @Override
+ public String getId() {
+ return "org.eclipse.debug.ui.commonTab"; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#canSave()
+ */
+ @Override
+ public boolean canSave() {
+ return validateLocalShared();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getImage()
+ */
+ @Override
+ public Image getImage() {
+ return DebugUITools.getImage(IInternalDebugUIConstants.IMG_OBJS_COMMON_TAB);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#activated(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ @Override
+ public void activated(ILaunchConfigurationWorkingCopy workingCopy) {}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.ILaunchConfigurationTab#deactivated(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+ */
+ @Override
+ public void deactivated(ILaunchConfigurationWorkingCopy workingCopy) {}
+
+ /**
+ * Content provider for the favorites table
+ */
+ class FavoritesContentProvider implements IStructuredContentProvider {
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ ILaunchGroup[] groups = DebugUITools.getLaunchGroups();
+ List possibleGroups = new ArrayList();
+ ILaunchConfiguration configuration = (ILaunchConfiguration)inputElement;
+ for (int i = 0; i < groups.length; i++) {
+ ILaunchGroup extension = groups[i];
+ LaunchHistory history = getLaunchConfigurationManager().getLaunchHistory(extension.getIdentifier());
+ if (history != null && history.accepts(configuration)) {
+ possibleGroups.add(extension);
+ }
+ }
+ return possibleGroups.toArray();
+ }
+
+ @Override
+ public void dispose() {}
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
+
+ }
+
+ /**
+ * Provides the labels for the favorites table
+ *
+ */
+ class FavoritesLabelProvider implements ITableLabelProvider {
+
+ private Map fImages = new HashMap();
+
+ @Override
+ public Image getColumnImage(Object element, int columnIndex) {
+ Image image = (Image)fImages.get(element);
+ if (image == null) {
+ ImageDescriptor descriptor = ((LaunchGroupExtension)element).getImageDescriptor();
+ if (descriptor != null) {
+ image = descriptor.createImage();
+ fImages.put(element, image);
+ }
+ }
+ return image;
+ }
+
+ @Override
+ public String getColumnText(Object element, int columnIndex) {
+ String label = ((LaunchGroupExtension)element).getLabel();
+ return DebugUIPlugin.removeAccelerators(label);
+ }
+
+ @Override
+ public void addListener(ILabelProviderListener listener) {}
+
+ @Override
+ public void dispose() {
+ Iterator images = fImages.values().iterator();
+ while (images.hasNext()) {
+ Image image = (Image)images.next();
+ image.dispose();
+ }
+ }
+
+ @Override
+ public boolean isLabelProperty(Object element, String property) {return false;}
+
+ @Override
+ public void removeListener(ILabelProviderListener listener) {}
+ }
+
+}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupCycleHandler.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupCycleHandler.java
new file mode 100644
index 000000000..746cc7581
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupCycleHandler.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2016 SSI Schaefer 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:
+ * SSI Schaefer - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.groups;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.IStatusHandler;
+import org.eclipse.debug.internal.ui.DebugUIMessages;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Handles the case that a group is nested within itself.
+ *
+ * @since 3.12
+ */
+public class GroupCycleHandler implements IStatusHandler {
+
+ @Override
+ public Object handleStatus(IStatus status, final Object source) throws CoreException {
+ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), DebugUIMessages.GroupLaunch_Error, NLS.bind(DebugUIMessages.GroupLaunch_Cycle, source.toString()));
+ }
+ });
+ return null;
+ }
+
+}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupElementLaunchedHandler.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupElementLaunchedHandler.java
new file mode 100644
index 000000000..24d276ce9
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupElementLaunchedHandler.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2016 SSI Schaefer 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:
+ * SSI Schaefer - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.groups;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.IStatusHandler;
+import org.eclipse.debug.internal.ui.DebugUIPlugin;
+
+/**
+ * Handles additionally required actions when a member of a group has been
+ * launched
+ *
+ * @since 3.12
+ */
+public class GroupElementLaunchedHandler implements IStatusHandler {
+
+ @Override
+ public Object handleStatus(IStatus status, Object source) throws CoreException {
+ if (source instanceof ILaunch[]) {
+ ILaunch[] launches = (ILaunch[]) source;
+
+ // Now we need to override the history to make multi-launch
+ // appear last, if we don't do it last launch would be our
+ // child's launch which is not correct for repeating the
+ // experience.
+ DebugUIPlugin.getDefault().getLaunchConfigurationManager().setRecentLaunch(launches[0]);
+ }
+ return null;
+ }
+
+}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationSelectionDialog.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationSelectionDialog.java
new file mode 100644
index 000000000..4c80c80b5
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationSelectionDialog.java
@@ -0,0 +1,399 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2016 QNX Software Systems 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:
+ * QNX Software Systems - initial API and implementation
+ * Freescale Semiconductor
+ * SSI Schaefer
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.groups;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationType;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.internal.core.groups.GroupLaunchElement;
+import org.eclipse.debug.internal.core.groups.GroupLaunchElement.GroupElementPostLaunchAction;
+import org.eclipse.debug.internal.ui.DebugUIMessages;
+import org.eclipse.debug.internal.ui.DebugUIPlugin;
+import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationFilteredTree;
+import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationManager;
+import org.eclipse.debug.internal.ui.launchConfigurations.LaunchGroupFilter;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.ILaunchGroup;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.TitleAreaDialog;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.ui.dialogs.FilteredTree;
+import org.eclipse.ui.dialogs.PatternFilter;
+
+/**
+ * Dialog to select launch configuration(s)
+ */
+class GroupLaunchConfigurationSelectionDialog extends TitleAreaDialog implements ISelectionChangedListener {
+ private ISelection fSelection;
+ private ILaunchGroup[] launchGroups;
+ private String mode;
+ private GroupElementPostLaunchAction action = GroupElementPostLaunchAction.NONE;
+ private Object actionParam;
+ private ViewerFilter emptyTypeFilter;
+ private IStructuredSelection fInitialSelection;
+ private ComboControlledStackComposite fStackComposite;
+ private Label fDelayAmountLabel;
+ private Text fDelayAmountWidget; // in seconds
+ private boolean fForEditing; // true if dialog was opened to edit an entry,
+ // otherwise it was opened to add one
+
+ public GroupLaunchConfigurationSelectionDialog(Shell shell, String initMode, boolean forEditing, ILaunchConfiguration self) {
+ super(shell);
+ LaunchConfigurationManager manager = DebugUIPlugin.getDefault().getLaunchConfigurationManager();
+ launchGroups = manager.getLaunchGroups();
+ mode = initMode;
+ fForEditing = forEditing;
+ setShellStyle(getShellStyle() | SWT.RESIZE);
+ emptyTypeFilter = new ViewerFilter() {
+ @Override
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ try {
+ if (element instanceof ILaunchConfigurationType) {
+ ILaunchConfigurationType type = (ILaunchConfigurationType) element;
+ if (type.equals(self.getType())) {
+ // we're hiding ourselves. if we're the only group,
+ // don't show the type.
+ return getLaunchManager().getLaunchConfigurations(type).length > 1;
+ }
+
+ return getLaunchManager().getLaunchConfigurations(type).length > 0;
+ } else if (element instanceof ILaunchConfiguration) {
+ ILaunchConfiguration c = (ILaunchConfiguration) element;
+ if (c.getName().equals(self.getName()) && c.getType().equals(self.getType())) {
+ return false;
+ }
+
+ if (c.getAttribute(IDebugUIConstants.ATTR_PRIVATE, false)) {
+ return false;
+ }
+
+ return GroupLaunchConfigurationTabGroup.isValidLaunchReference(c);
+ }
+ return true;
+ } catch (CoreException e) {
+ return false;
+ }
+ }
+ };
+ }
+
+ protected ILaunchManager getLaunchManager() {
+ return DebugPlugin.getDefault().getLaunchManager();
+ }
+
+ @Override
+ protected Control createContents(Composite parent) {
+ Control x = super.createContents(parent);
+ validate();
+ setErrorMessage(null);
+ return x;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent2) {
+ Composite comp = (Composite) super.createDialogArea(parent2);
+
+ // title bar
+ getShell().setText(fForEditing ? DebugUIMessages.GroupLaunchConfigurationSelectionDialog_13 : DebugUIMessages.GroupLaunchConfigurationSelectionDialog_12);
+
+ // dialog message area (not title bar)
+ setTitle(fForEditing ? DebugUIMessages.GroupLaunchConfigurationSelectionDialog_15 : DebugUIMessages.GroupLaunchConfigurationSelectionDialog_14);
+
+ fStackComposite = new ComboControlledStackComposite(comp, SWT.NONE);
+
+ Map<String, ILaunchGroup> modes = new TreeMap<>();
+ for (ILaunchGroup launchGroup : launchGroups) {
+ if (!modes.containsKey(launchGroup.getMode())) {
+ modes.put(launchGroup.getMode(), launchGroup);
+ }
+ }
+ modes.put(GroupLaunchElement.MODE_INHERIT, new InheritModeGroup());
+
+ for (Map.Entry<String, ILaunchGroup> entry : modes.entrySet()) {
+ ILaunchGroup launchGroup = entry.getValue();
+ LaunchConfigurationFilteredTree fTree = new LaunchConfigurationFilteredTree(fStackComposite.getStackParent(), SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER, new PatternFilter(), launchGroup, null);
+ String lgm = entry.getKey();
+ fStackComposite.addItem(lgm, fTree);
+ fTree.createViewControl();
+ ViewerFilter[] filters = fTree.getViewer().getFilters();
+ for (ViewerFilter viewerFilter : filters) {
+ if (viewerFilter instanceof LaunchGroupFilter) {
+ fTree.getViewer().removeFilter(viewerFilter);
+ }
+ }
+ fTree.getViewer().addFilter(emptyTypeFilter);
+ fTree.getViewer().addSelectionChangedListener(this);
+ if (lgm.equals(this.mode)) {
+ fStackComposite.setSelection(lgm);
+ }
+ if (fInitialSelection != null) {
+ fTree.getViewer().setSelection(fInitialSelection, true);
+ }
+ }
+ fStackComposite.setLabelText(DebugUIMessages.GroupLaunchConfigurationSelectionDialog_4);
+ fStackComposite.pack();
+ Rectangle bounds = fStackComposite.getBounds();
+ // adjust size
+ GridData data = ((GridData) fStackComposite.getLayoutData());
+ if (data == null) {
+ data = new GridData(GridData.FILL_BOTH);
+ fStackComposite.setLayoutData(data);
+ }
+ data.heightHint = Math.max(convertHeightInCharsToPixels(15), bounds.height);
+ data.widthHint = Math.max(convertWidthInCharsToPixels(40), bounds.width);
+ fStackComposite.getCombo().addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ mode = ((Combo) e.widget).getText();
+ }
+ });
+
+ createPostLaunchControl(comp);
+ return comp;
+ }
+
+ private void createPostLaunchControl(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE);
+ comp.setLayout(new GridLayout(4, false));
+ comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ Label label = new Label(comp, SWT.NONE);
+ label.setText(DebugUIMessages.GroupLaunchConfigurationSelectionDialog_8);
+ Combo combo = new Combo(comp, SWT.READ_ONLY);
+ combo.add(GroupElementPostLaunchAction.NONE.getDescription());
+ combo.add(GroupElementPostLaunchAction.WAIT_FOR_TERMINATION.getDescription());
+ combo.add(GroupElementPostLaunchAction.DELAY.getDescription());
+ combo.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ final String actionStr = ((Combo) e.widget).getText();
+ action = GroupElementPostLaunchAction.valueOfDescription(actionStr);
+ showHideDelayAmountWidgets();
+ validate();
+ }
+ });
+ combo.setText(action.getDescription());
+
+ fDelayAmountLabel = new Label(comp, SWT.NONE);
+ fDelayAmountLabel.setText(DebugUIMessages.GroupLaunchConfigurationSelectionDialog_9);
+
+ fDelayAmountWidget = new Text(comp, SWT.SINGLE | SWT.BORDER);
+ GridData gridData = new GridData();
+ gridData.widthHint = convertWidthInCharsToPixels(8);
+ fDelayAmountWidget.setLayoutData(gridData);
+ fDelayAmountWidget.addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ String text = ((Text) e.widget).getText();
+ try {
+ actionParam = Integer.valueOf(text);
+ } catch (NumberFormatException exc) {
+ actionParam = null;
+ }
+ validate();
+ }
+ });
+ if (actionParam instanceof Integer) {
+ fDelayAmountWidget.setText(((Integer) actionParam).toString());
+ }
+
+ showHideDelayAmountWidgets();
+ }
+
+ private void showHideDelayAmountWidgets() {
+ final boolean visible = action == GroupElementPostLaunchAction.DELAY;
+ fDelayAmountLabel.setVisible(visible);
+ fDelayAmountWidget.setVisible(visible);
+ }
+
+ public ILaunchConfiguration[] getSelectedLaunchConfigurations() {
+ List<ILaunchConfiguration> configs = new ArrayList<ILaunchConfiguration>();
+ if (fSelection != null && !fSelection.isEmpty()) {
+ for (Iterator<?> iter = ((IStructuredSelection) fSelection).iterator(); iter.hasNext();) {
+ Object selection = iter.next();
+ if (selection instanceof ILaunchConfiguration) {
+ configs.add((ILaunchConfiguration) selection);
+ }
+ }
+ }
+ return configs.toArray(new ILaunchConfiguration[configs.size()]);
+ }
+
+ public String getMode() {
+ return mode;
+ }
+
+ public GroupElementPostLaunchAction getAction() {
+ return action;
+ }
+
+ public Object getActionParam() {
+ return actionParam;
+ }
+
+ public static GroupLaunchConfigurationSelectionDialog createDialog(Shell shell, String initMode, boolean forEditing, ILaunchConfiguration self) {
+ return new GroupLaunchConfigurationSelectionDialog(shell, initMode, forEditing, self);
+ }
+
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+
+ // This listener gets called for a selection change in the launch
+ // configuration viewer embedded in the dialog. Problem is, there are
+ // numerous viewers--one for each platform debug ILaunchGroup (run,
+ // debug, profile). These viewers are stacked, so only one is ever
+ // visible to the user. During initialization, we get a selection change
+ // notification for every viewer. We need to ignore all but the one that
+ // matters--the visible one.
+
+ Tree topTree = null;
+ final Control topControl = fStackComposite.getTopControl();
+ if (topControl instanceof FilteredTree) {
+ final TreeViewer viewer = ((FilteredTree) topControl).getViewer();
+ if (viewer != null) {
+ topTree = viewer.getTree();
+ }
+ }
+ if (topTree == null) {
+ return;
+ }
+
+ boolean selectionIsForVisibleViewer = false;
+ final Object src = event.getSource();
+ if (src instanceof Viewer) {
+ final Control viewerControl = ((Viewer) src).getControl();
+ if (viewerControl == topTree) {
+ selectionIsForVisibleViewer = true;
+ }
+ }
+
+ if (!selectionIsForVisibleViewer) {
+ return;
+ }
+
+ fSelection = event.getSelection();
+ validate();
+ }
+
+ protected void validate() {
+ Button ok_button = getButton(IDialogConstants.OK_ID);
+ boolean isValid = true;
+ if (getSelectedLaunchConfigurations().length < 1) {
+ setErrorMessage(DebugUIMessages.GroupLaunchConfigurationSelectionDialog_7);
+ isValid = false;
+ } else {
+ setErrorMessage(null);
+ }
+
+ if (isValid) {
+ if (fForEditing) {
+ // must have only one selection
+ if (getSelectedLaunchConfigurations().length > 1) {
+ setErrorMessage(DebugUIMessages.GroupLaunchConfigurationSelectionDialog_11);
+ isValid = false;
+ }
+ }
+ }
+
+ if (isValid) {
+ if (action == GroupElementPostLaunchAction.DELAY) {
+ isValid = (actionParam instanceof Integer) && ((Integer) actionParam > 0);
+ setErrorMessage(isValid ? null : DebugUIMessages.GroupLaunchConfigurationSelectionDialog_10);
+ }
+ }
+
+ if (ok_button != null) {
+ ok_button.setEnabled(isValid);
+ }
+ }
+
+ public void setInitialSelection(GroupLaunchElement el) {
+ action = el.action;
+ actionParam = el.actionParam;
+ fInitialSelection = new StructuredSelection(el.data);
+ fSelection = fInitialSelection;
+ }
+
+ /**
+ * Required to satisfy the tree in mode inherit.
+ */
+ private static final class InheritModeGroup implements ILaunchGroup {
+
+ @Override
+ public ImageDescriptor getImageDescriptor() {
+ return null;
+ }
+
+ @Override
+ public ImageDescriptor getBannerImageDescriptor() {
+ return null;
+ }
+
+ @Override
+ public String getLabel() {
+ return null;
+ }
+
+ @Override
+ public String getIdentifier() {
+ return null;
+ }
+
+ @Override
+ public String getCategory() {
+ return null;
+ }
+
+ @Override
+ public String getMode() {
+ return null;
+ }
+
+ @Override
+ public boolean isPublic() {
+ return false;
+ }
+
+ }
+}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationTabGroup.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationTabGroup.java
new file mode 100644
index 000000000..b7140238f
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationTabGroup.java
@@ -0,0 +1,572 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2012, 2016 QNX Software Systems 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:
+ * QNX Software Systems - initial API and implementation
+ * Freescale Semiconductor
+ * SSI Schaefer
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.groups;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.internal.core.groups.GroupLaunchConfigurationDelegate;
+import org.eclipse.debug.internal.core.groups.GroupLaunchElement;
+import org.eclipse.debug.internal.core.groups.GroupLaunchElement.GroupElementPostLaunchAction;
+import org.eclipse.debug.internal.ui.DebugPluginImages;
+import org.eclipse.debug.internal.ui.DebugUIMessages;
+import org.eclipse.debug.internal.ui.DebugUIPlugin;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.ILaunchConfigurationDialog;
+import org.eclipse.debug.ui.ILaunchConfigurationTab;
+import org.eclipse.jface.viewers.BaseLabelProvider;
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.ICheckStateProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.window.Window;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeColumn;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.activities.WorkbenchActivityHelper;
+
+/**
+ * Tab group for Launch Group.
+ *
+ * @since 3.12
+ */
+public class GroupLaunchConfigurationTabGroup extends AbstractLaunchConfigurationTabGroup {
+ static class ContentProvider implements IStructuredContentProvider, ITreeContentProvider {
+ protected List<GroupLaunchElement> input;
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ return getChildren(inputElement);
+ }
+
+ @Override
+ public void dispose() {
+ input = null;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked") // nothing we can do about this
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ if (newInput instanceof List<?>) {
+ input = (List<GroupLaunchElement>) newInput;
+ }
+ }
+
+ @Override
+ public Object[] getChildren(Object parentElement) {
+ return (parentElement == input) ? input.toArray() : null;
+ }
+
+ @Override
+ public Object getParent(Object element) {
+ return (element == input) ? null : input;
+ }
+
+ @Override
+ public boolean hasChildren(Object element) {
+ return (element == input) ? (input.size() > 0) : false;
+ }
+ }
+ static class LabelProvider extends BaseLabelProvider implements ITableLabelProvider {
+ @Override
+ public Image getColumnImage(Object element, int columnIndex) {
+ if (!(element instanceof GroupLaunchElement)) {
+ return null;
+ }
+ if (columnIndex == 0) {
+ GroupLaunchElement el = (GroupLaunchElement) element;
+ if (el.data == null || !isValidLaunchReference(el.data)) {
+ Image errorImage = PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
+ return errorImage;
+ }
+
+ try {
+ String key = el.data.getType().getIdentifier();
+ return DebugPluginImages.getImage(key);
+ } catch (CoreException e) {
+ Image errorImage = PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
+ return errorImage;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String getColumnText(Object element, int columnIndex) {
+ if (!(element instanceof GroupLaunchElement)) {
+ return null;
+ }
+ GroupLaunchElement el = (GroupLaunchElement) element;
+
+ // launch name
+ if (columnIndex == 0) {
+ try {
+ return (el.data != null) ? el.data.getType().getName() + "::" + el.name : el.name; //$NON-NLS-1$
+ } catch (CoreException e) {
+ return el.name;
+ }
+ }
+
+ // launch mode
+ if (columnIndex == 1) {
+ return el.mode;
+ }
+
+ // launch post action
+ if (columnIndex == 2) {
+ GroupElementPostLaunchAction action = el.action;
+ switch (action) {
+ case NONE:
+ return ""; //$NON-NLS-1$
+ case WAIT_FOR_TERMINATION:
+ return action.getDescription();
+ case DELAY:
+ final Object actionParam = el.actionParam;
+ return NLS.bind(DebugUIMessages.GroupLaunchConfigurationTabGroup_13,
+ actionParam instanceof Integer ? Integer.toString((Integer) actionParam) : "?"); //$NON-NLS-1$
+ default:
+ assert false : "new post launch action missing logic here"; //$NON-NLS-1$
+ return ""; //$NON-NLS-1$
+ }
+ }
+ return null;
+ }
+ }
+
+ static class CheckStateProvider implements ICheckStateProvider {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ICheckStateProvider#isChecked(java.lang.Object)
+ */
+ @Override
+ public boolean isChecked(Object element) {
+ if (element instanceof GroupLaunchElement) {
+ return ((GroupLaunchElement)element).enabled;
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.viewers.ICheckStateProvider#isGrayed(java.lang.Object)
+ */
+ @Override
+ public boolean isGrayed(Object element) {
+ return false;
+ }
+ }
+ static abstract class ButtonComposite extends Composite implements SelectionListener {
+ Button upButton;
+ Button downButton;
+ Button addButton;
+ Button deleteButton;
+ Button editButton;
+
+ public ButtonComposite(Composite parent, int style) {
+ super(parent, style);
+ setLayout(new GridLayout());
+ upButton = createPushButton(this, DebugUIMessages.GroupLaunchConfigurationTabGroup_1);
+ downButton = createPushButton(this, DebugUIMessages.GroupLaunchConfigurationTabGroup_2);
+ editButton = createPushButton(this, DebugUIMessages.GroupLaunchConfigurationTabGroup_3);
+ addButton = createPushButton(this, DebugUIMessages.GroupLaunchConfigurationTabGroup_4);
+ deleteButton = createPushButton(this, DebugUIMessages.GroupLaunchConfigurationTabGroup_5);
+ }
+
+ protected abstract void updateWidgetEnablement();
+
+ /**
+ * Helper method to create a push button.
+ *
+ * @param parent
+ * the parent control
+ * @param key
+ * the resource name used to supply the button's label text
+ * @return Button
+ */
+ protected Button createPushButton(Composite parent, String key) {
+ Button button = new Button(parent, SWT.PUSH);
+ button.setText(key);
+ button.setFont(parent.getFont());
+ GridData data = new GridData(GridData.FILL_HORIZONTAL);
+ button.setLayoutData(data);
+ button.addSelectionListener(this);
+ return button;
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ // nothing
+ }
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ Widget widget = e.widget;
+ if (widget == upButton) {
+ upPressed();
+ } else if (widget == downButton) {
+ downPressed();
+ } else if (widget == addButton) {
+ addPressed();
+ } else if (widget == deleteButton) {
+ deletePressed();
+ } else if (widget == editButton) {
+ editPressed();
+ }
+ }
+
+ protected abstract void addPressed();
+
+ protected abstract void editPressed();
+
+ protected abstract void deletePressed();
+
+ protected abstract void downPressed();
+
+ protected abstract void upPressed();
+ }
+ static class GroupLaunchTab extends AbstractLaunchConfigurationTab {
+ protected CheckboxTreeViewer treeViewer;
+ protected List<GroupLaunchElement> input = new ArrayList<GroupLaunchElement>();
+
+ /**
+ * copy of the initial state of the configuration used for cycle
+ * checking. This is not updated when the user changes settings!
+ */
+ private ILaunchConfiguration self;
+
+ @Override
+ public void createControl(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE);
+ setControl(comp);
+ //comp.setBackground(PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_DARK_GREEN));
+ comp.setLayout(new GridLayout(2, false));
+ treeViewer = new CheckboxTreeViewer(comp, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
+ Tree table = treeViewer.getTree();
+ table.setFont(parent.getFont());
+ treeViewer.setContentProvider(new ContentProvider());
+ treeViewer.setLabelProvider(new LabelProvider());
+ treeViewer.setCheckStateProvider(new CheckStateProvider());
+ table.setHeaderVisible(true);
+ table.setLayoutData(new GridData(GridData.FILL_BOTH));
+ TreeColumn col1 = new TreeColumn(table, SWT.NONE);
+ col1.setText(DebugUIMessages.GroupLaunchConfigurationTabGroup_6);
+ col1.setWidth(300);
+ TreeColumn col2 = new TreeColumn(table, SWT.NONE);
+ col2.setText(DebugUIMessages.GroupLaunchConfigurationTabGroup_7);
+ col2.setWidth(100);
+ TreeColumn col3 = new TreeColumn(table, SWT.NONE);
+ col3.setText(DebugUIMessages.GroupLaunchConfigurationTabGroup_12);
+ col3.setWidth(100);
+
+ treeViewer.setInput(input);
+ final ButtonComposite buts = new ButtonComposite(comp, SWT.NONE) {
+ @Override
+ protected void addPressed() {
+ GroupLaunchConfigurationSelectionDialog dialog =
+ GroupLaunchConfigurationSelectionDialog.createDialog(
+ treeViewer.getControl().getShell(), GroupLaunchElement.MODE_INHERIT, false, self);
+ if (dialog.open() == Window.OK) {
+ ILaunchConfiguration[] configs = dialog.getSelectedLaunchConfigurations();
+ if (configs.length < 1) {
+ return;
+ }
+ for (ILaunchConfiguration config : configs) {
+ GroupLaunchElement el = new GroupLaunchElement();
+ input.add(el);
+ el.index = input.size() - 1;
+ el.enabled = true;
+ el.name = config.getName();
+ el.data = config;
+ el.mode = dialog.getMode();
+ el.action = dialog.getAction();
+ el.actionParam = dialog.getActionParam();
+ treeViewer.refresh(true);
+ treeViewer.setChecked(el, el.enabled);
+ }
+ updateWidgetEnablement();
+ updateLaunchConfigurationDialog();
+ }
+ }
+ @Override
+ protected void updateWidgetEnablement(){
+ downButton.setEnabled(isDownEnabled());
+ upButton.setEnabled(isUpEnabled());
+
+ int selectionCount = getSelectionCount();
+ editButton.setEnabled(selectionCount == 1);
+ deleteButton.setEnabled(selectionCount > 0);
+ }
+
+
+ @Override
+ protected void editPressed() {
+ int index = getSingleSelectionIndex();
+ if (index < 0) {
+ return;
+ }
+ GroupLaunchElement el = input.get(index);
+ GroupLaunchConfigurationSelectionDialog dialog =
+ GroupLaunchConfigurationSelectionDialog.createDialog(
+ treeViewer.getControl().getShell(), el.mode, true, self);
+ if (isValidLaunchReference(el.data)) {
+ dialog.setInitialSelection(el);
+ }
+ if (dialog.open() == Window.OK) {
+ ILaunchConfiguration[] confs = dialog.getSelectedLaunchConfigurations();
+ if (confs.length < 0) {
+ return;
+ }
+ assert confs.length == 1 : "invocation of the dialog for editing an entry sholdn't allow OK to be hit if the user chooses multiple launch configs in the dialog"; //$NON-NLS-1$
+ el.name = confs[0].getName();
+ el.data = confs[0];
+ el.mode = dialog.getMode();
+ el.action = dialog.getAction();
+ el.actionParam = dialog.getActionParam();
+ treeViewer.refresh(true);
+ updateWidgetEnablement();
+ updateLaunchConfigurationDialog();
+ }
+ }
+ @Override
+ protected void deletePressed() {
+ int[] indices = getMultiSelectionIndices();
+ if (indices.length < 1) {
+ return;
+ }
+ // need to delete from high to low
+ for (int i = indices.length - 1; i >= 0; i--) {
+ input.remove(indices[i]);
+ }
+ treeViewer.refresh(true);
+ updateWidgetEnablement();
+ updateLaunchConfigurationDialog();
+ }
+
+ /**
+ * @return the index of the selection if a single item is
+ * selected. If zero or multiple are selected, -1 is
+ * returned
+ */
+ private int getSingleSelectionIndex() {
+ StructuredSelection sel = (StructuredSelection) treeViewer.getSelection();
+ if (sel.size() != 1) {
+ return -1;
+ }
+ GroupLaunchElement el = ((GroupLaunchElement) sel
+ .getFirstElement());
+ return input.indexOf(el);
+ }
+
+ /**
+ * @return the indices of one or more selected items. Indices
+ * are always returned in ascending order
+ */
+ private int[] getMultiSelectionIndices() {
+ StructuredSelection sel = (StructuredSelection) treeViewer.getSelection();
+ List<Integer> indices = new ArrayList<Integer>();
+
+ for (Iterator<?> iter = sel.iterator(); iter.hasNext(); ) {
+ GroupLaunchElement el = (GroupLaunchElement) iter.next();
+ indices.add(input.indexOf(el));
+
+ }
+ int[] result = new int[indices.size()];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = indices.get(i);
+ }
+ return result;
+ }
+
+ private int getSelectionCount() {
+ return ((StructuredSelection)treeViewer.getSelection()).size();
+ }
+
+
+ @Override
+ protected void downPressed() {
+ if (!isDownEnabled()) {
+ return;
+ }
+ int index = getSingleSelectionIndex();
+
+ GroupLaunchElement x = input.get(index);
+ input.set(index, input.get(index + 1));
+ input.set(index + 1, x);
+ treeViewer.refresh(true);
+ updateWidgetEnablement();
+ updateLaunchConfigurationDialog();
+ }
+
+ protected boolean isDownEnabled() {
+ final int index = getSingleSelectionIndex();
+ return (index >= 0) && (index != input.size() - 1);
+ }
+
+ protected boolean isUpEnabled(){
+ return getSingleSelectionIndex() > 0;
+ }
+
+ @Override
+ protected void upPressed() {
+ if (!isUpEnabled()) {
+ return;
+ }
+ int index = getSingleSelectionIndex();
+ GroupLaunchElement x = input.get(index);
+ input.set(index, input.get(index - 1));
+ input.set(index - 1, x);
+ treeViewer.refresh(true);
+ updateWidgetEnablement();
+ updateLaunchConfigurationDialog();
+ }
+ };
+ treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ buts.updateWidgetEnablement();
+ }
+ });
+
+ treeViewer.getTree().addSelectionListener(new SelectionAdapter(){
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ buts.editPressed();
+ }
+ });
+
+ treeViewer.addCheckStateListener(new ICheckStateListener(){
+ @Override
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ ((GroupLaunchElement)event.getElement()).enabled = event.getChecked();
+ updateLaunchConfigurationDialog();
+ }
+ });
+ buts.updateWidgetEnablement();
+ GridData layoutData = new GridData(GridData.GRAB_VERTICAL);
+ layoutData.verticalAlignment = SWT.BEGINNING;
+ buts.setLayoutData(layoutData);
+ }
+
+ @Override
+ public String getName() {
+ return DebugUIMessages.GroupLaunchConfigurationTabGroup_10;
+ }
+
+ @Override
+ public void initializeFrom(ILaunchConfiguration configuration) {
+ try {
+ self = configuration.copy(configuration.getName());
+ } catch (CoreException e) {
+ DebugPlugin.log(e);
+ }
+
+ // replace the input from previously shown launch configurations
+ input = GroupLaunchConfigurationDelegate.createLaunchElements(configuration);
+ if (treeViewer != null) {
+ treeViewer.setInput(input);
+ }
+ }
+
+ @Override
+ public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+ GroupLaunchConfigurationDelegate.storeLaunchElements(configuration, input);
+ }
+
+ @Override
+ public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+ // defaults is empty list
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
+ */
+ @Override
+ public boolean isValid(ILaunchConfiguration launchConfig) {
+ setMessage(null);
+ setErrorMessage(null);
+ int validLaunches = 0;
+ // test if each launch is valid
+ for (GroupLaunchElement element : input) {
+ if (element.enabled) {
+ if ( element.data == null) {
+ // error referencing invalid launch
+ setErrorMessage(MessageFormat.format(DebugUIMessages.GroupLaunchConfigurationTabGroup_14,
+ element.name));
+ return false;
+ } else if (!isValidLaunchReference(element.data)) {
+ // error referencing invalid launch
+ setErrorMessage(MessageFormat.format(DebugUIMessages.GroupLaunchConfigurationTabGroup_15,
+ element.name));
+ return false;
+ }
+ validLaunches++;
+ }
+ }
+ if (validLaunches < 1) {
+ // must have at least one valid and enabled launch
+ setErrorMessage(DebugUIMessages.GroupLaunchConfigurationTabGroup_16);
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public GroupLaunchConfigurationTabGroup() {
+ // nothing
+ }
+
+ /**
+ * Test if a launch configuration is a valid reference.
+ *
+ * @param config configuration reference
+ * @return <code>true</code> if it is a valid reference, <code>false</code>
+ * if launch configuration should be filtered
+ */
+ public static boolean isValidLaunchReference(ILaunchConfiguration config) {
+ return DebugUIPlugin.doLaunchConfigurationFiltering(config) && !WorkbenchActivityHelper.filterItem(config);
+ }
+
+ @Override
+ public void createTabs(ILaunchConfigurationDialog dialog, String mode) {
+ ILaunchConfigurationTab[] tabs = new ILaunchConfigurationTab[] {//
+ new GroupLaunchTab(), //
+ new CommonTabLite() //
+ };
+ setTabs(tabs);
+ }
+}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchHandler.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchHandler.java
new file mode 100644
index 000000000..799a34a90
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchHandler.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2016 SSI Schaefer 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:
+ * SSI Schaefer - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.groups;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.IStatusHandler;
+import org.eclipse.debug.internal.core.groups.GroupLaunchConfigurationDelegate;
+import org.eclipse.debug.internal.ui.DebugUIPlugin;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * Handles the states whenever a group launch begins, and when one is done
+ * launching.
+ * <p>
+ * The implementation uses some static variables to keep track as
+ * IStatusHandlers are instantiated from scratch for each state change.
+ *
+ * @since 3.12
+ */
+public class GroupLaunchHandler implements IStatusHandler {
+
+ private static AtomicInteger launchCounter = new AtomicInteger(0);
+ private static boolean removeLaunchesState = false;
+
+ @Override
+ public Object handleStatus(IStatus status, Object source) throws CoreException {
+ final IPreferenceStore prefStore = DebugUIPlugin.getDefault().getPreferenceStore();
+
+ switch (status.getCode()) {
+ case GroupLaunchConfigurationDelegate.CODE_GROUP_LAUNCH_START:
+ int prevCount = launchCounter.getAndIncrement();
+ if (prevCount == 0) {
+ // Have to temporarily turn off the "remove terminated
+ // launches when new one created" preference because it does
+ // not work well for group launches
+ removeLaunchesState = prefStore.getBoolean(IDebugUIConstants.PREF_AUTO_REMOVE_OLD_LAUNCHES);
+ prefStore.setValue(IDebugUIConstants.PREF_AUTO_REMOVE_OLD_LAUNCHES, false);
+ }
+ break;
+ case GroupLaunchConfigurationDelegate.CODE_GROUP_LAUNCH_DONE:
+ int newCount = launchCounter.decrementAndGet();
+ if (newCount == 0) {
+ prefStore.setValue(IDebugUIConstants.PREF_AUTO_REMOVE_OLD_LAUNCHES, removeLaunchesState);
+ }
+ break;
+ default:
+ // unknown state...
+ break;
+ }
+ return null;
+ }
+
+}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/UnsupportedModeHandler.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/UnsupportedModeHandler.java
new file mode 100644
index 000000000..cc58548d5
--- /dev/null
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/UnsupportedModeHandler.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2016 SSI Schaefer 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:
+ * SSI Schaefer - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.internal.ui.groups;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.IStatusHandler;
+import org.eclipse.debug.internal.ui.DebugUIMessages;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Handles the case where a launch configuration in a group cannot be launched
+ * in the requested mode.
+ *
+ * @since 3.12
+ */
+public class UnsupportedModeHandler implements IStatusHandler {
+
+ @Override
+ public Object handleStatus(IStatus status, Object source) throws CoreException {
+ if (source instanceof String[]) {
+ final String[] data = (String[]) source;
+ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), DebugUIMessages.GroupLaunch_Error, NLS.bind(DebugUIMessages.GroupLaunch_Cannot_launch, data[0], data[1]));
+ }
+ });
+ }
+ return null;
+ }
+
+}

Back to the top