blob: 4ccd135140eded8242481e70e44e1ed14eb55076 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2018 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.debug.internal.ui.preferences;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.internal.core.LaunchManager;
import org.eclipse.debug.internal.ui.AbstractDebugListSelectionDialog;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.DefaultLabelProvider;
import org.eclipse.debug.internal.ui.IDebugHelpContextIds;
import org.eclipse.debug.internal.ui.SWTFactory;
import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationComparator;
import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationManager;
import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsDialog;
import org.eclipse.debug.ui.ILaunchGroup;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
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.TableViewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.Table;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PropertyPage;
import org.eclipse.ui.dialogs.SelectionDialog;
/**
* Displays default launch configuration settings for a selected resource - associated launch configurations.
*
* @see PropertyPage
* @see ILaunchConfiguration
* @see LaunchConfigurationsDialog
*
* CONTEXTLAUNCHING
*
* @since 3.3.0
*/
public class RunDebugPropertiesPage extends PropertyPage {
/**
* Set of configurations to be deleted
*/
private Set<ILaunchConfigurationWorkingCopy> fDeletedConfigurations = new HashSet<>();
/**
* Set of original default candidates for the resource
*/
private Set<ILaunchConfiguration> fOriginalCandidates;
/**
* Holds configurations that need to be saved when the page closes
*/
private Set<ILaunchConfigurationWorkingCopy> fChangedConfigurations = new HashSet<>();
/**
* List of the applicable launch config types for the backing resource
*/
private List<ILaunchConfigurationType> fTypeCandidates = null;
//widgets
private TableViewer fViewer;
private Button fNewButton = null;
private Button fEditButton = null;
private Button fDuplicateButton = null;
private Button fDeleteButton = null;
@Override
protected Control createContents(Composite parent) {
PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, IDebugHelpContextIds.RUN_DEBUG_RESOURCE_PROPERTY_PAGE);
collectConfigCandidates(getResource());
Composite topComposite = SWTFactory.createComposite(parent, 2, 1, GridData.FILL_BOTH);
SWTFactory.createWrapLabel(topComposite, DebugPreferencesMessages.DefaultLaunchConfigurationsPropertiesPage_0, 2, 300);
SWTFactory.createVerticalSpacer(topComposite, 2);
SWTFactory.createWrapLabel(topComposite, MessageFormat.format(DebugPreferencesMessages.DefaultLaunchConfigurationsPropertiesPage_1, new Object[] { getResource().getName() }), 2, 300);
fViewer = createViewer(topComposite);
Composite buttonComp = SWTFactory.createComposite(topComposite, 1, 1, GridData.FILL_VERTICAL);
GridLayout layout = (GridLayout) buttonComp.getLayout();
layout.marginHeight = 0;
fNewButton = SWTFactory.createPushButton(buttonComp, DebugPreferencesMessages.DefaultLaunchConfigurationsPropertiesPage_2, null);
fNewButton.setToolTipText(DebugPreferencesMessages.DefaultLaunchConfigurationsPropertiesPage_3);
fNewButton.setEnabled(collectTypeCandidates().length > 0);
fNewButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {}
@Override
public void widgetSelected(SelectionEvent e) {
handleNew();
}
});
fDuplicateButton = SWTFactory.createPushButton(buttonComp, DebugPreferencesMessages.DefaultLaunchConfigurationsPropertiesPage_4, null);
fDuplicateButton.setToolTipText(DebugPreferencesMessages.DefaultLaunchConfigurationsPropertiesPage_5);
fDuplicateButton.setEnabled(false);
fDuplicateButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {}
@Override
public void widgetSelected(SelectionEvent e) {
handleCopy();
}
});
fEditButton = SWTFactory.createPushButton(buttonComp, DebugPreferencesMessages.DefaultLaunchConfigurationsPropertiesPage_6, null);
fEditButton.setToolTipText(DebugPreferencesMessages.DefaultLaunchConfigurationsPropertiesPage_7);
fEditButton.setEnabled(false);
fEditButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {}
@Override
public void widgetSelected(SelectionEvent e) {
handleEdit();
}
});
fDeleteButton = SWTFactory.createPushButton(buttonComp, DebugPreferencesMessages.DefaultLaunchConfigurationsPropertiesPage_8, null);
fDeleteButton.setToolTipText(DebugPreferencesMessages.DefaultLaunchConfigurationsPropertiesPage_9);
fDeleteButton.setEnabled(false);
fDeleteButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {}
@Override
public void widgetSelected(SelectionEvent e) {
handleDelete();
}
});
fViewer.setSelection(new StructuredSelection());
applyDialogFont(topComposite);
return topComposite;
}
/**
* Creates and returns the viewer that will display the possible default configurations.
*
* @param parent parent composite to create the viewer in
* @return viewer viewer that will display possible default configurations
*/
protected TableViewer createViewer(Composite parent){
TableViewer viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER);
viewer.setLabelProvider(new DefaultLabelProvider());
viewer.setContentProvider(new ArrayContentProvider());
viewer.setComparator(new LaunchConfigurationComparator());
Table builderTable = viewer.getTable();
GridData tableGridData = new GridData(GridData.FILL_BOTH);
tableGridData.heightHint = 300;
tableGridData.widthHint = 300;
builderTable.setLayoutData(tableGridData);
IResource resource = getResource();
viewer.setInput(collectConfigCandidates(resource));
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
ISelection sel = event.getSelection();
if(sel instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection) sel;
boolean empty = ss.isEmpty();
int size = ss.size();
fEditButton.setEnabled(!empty && size == 1);
fDuplicateButton.setEnabled(!empty && size == 1);
fDeleteButton.setEnabled(!empty);
setErrorMessage(null);
}
}
});
viewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent arg0) {
handleEdit();
}
});
return viewer;
}
@Override
public void dispose() {
if(fOriginalCandidates != null) {
fOriginalCandidates.clear();
fOriginalCandidates = null;
}
if(fChangedConfigurations != null) {
fChangedConfigurations.clear();
fChangedConfigurations = null;
}
super.dispose();
}
/**
* Returns the viewer displaying possible default configurations.
*
* @return viewer
*/
protected TableViewer getViewer() {
return fViewer;
}
/**
* Returns the launch manager
* @return the launch manager
*/
protected LaunchManager getLaunchManager() {
return (LaunchManager) DebugPlugin.getDefault().getLaunchManager();
}
/**
* Collects the applicable launch configuration types for the backing resource.
* Default implementation uses the launch shortcut evaluation expressions and leverages the
* mapping of launch shortcut to config type id to derive the applicable types.
* @return the listing of applicable launch configuration types for the backing resource
*/
protected ILaunchConfigurationType[] collectTypeCandidates() {
if(fTypeCandidates == null) {
String[] types = DebugUIPlugin.getDefault().getLaunchConfigurationManager().getApplicableConfigurationTypes(getResource());
fTypeCandidates = new ArrayList<>(types.length);
for (String type : types) {
fTypeCandidates.add(DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(type));
}
Collections.sort(fTypeCandidates, new Comparator<ILaunchConfigurationType>() {
@Override
public int compare(ILaunchConfigurationType o1, ILaunchConfigurationType o2) {
ILaunchConfigurationType t1 = o1;
ILaunchConfigurationType t2 = o2;
return t1.getName().compareTo(t2.getName());
}
});
}
return fTypeCandidates.toArray(new ILaunchConfigurationType[fTypeCandidates.size()]);
}
/**
* Returns a set of potential default configurations candidates for the given
* resource. The configurations are working copies.
*
* @param resource resource
* @return list of default candidates
*/
protected Set<ILaunchConfiguration> collectConfigCandidates(IResource resource) {
if(fOriginalCandidates == null) {
fOriginalCandidates = new HashSet<>();
try {
ILaunchConfiguration[] configs = DebugUIPlugin.getDefault().getLaunchConfigurationManager().getApplicableLaunchConfigurations(null, resource);
for (ILaunchConfiguration config : configs) {
fOriginalCandidates.add(config.getWorkingCopy());
}
}
catch(CoreException ce) {DebugUIPlugin.log(ce);}
}
return fOriginalCandidates;
}
/**
* Returns the resource this property page is open on.
*
* @return resource
*/
protected IResource getResource() {
IAdaptable element = getElement();
IResource resource = null;
if (element instanceof IResource) {
resource = (IResource) element;
} else if (element != null) {
resource = element.getAdapter(IResource.class);
}
return resource;
}
@Override
public boolean performOk() {
//delete
for (ILaunchConfigurationWorkingCopy currentConfig : fDeletedConfigurations) {
try{
if (currentConfig.getOriginal() != null){
currentConfig.getOriginal().delete();
}
} catch (CoreException e) {
DebugPlugin.logMessage("Problem deleting configuration " + currentConfig.getName(), e); //$NON-NLS-1$
}
}
//add
for (ILaunchConfigurationWorkingCopy currentConfig : fChangedConfigurations) {
try{
currentConfig.doSave();
} catch (CoreException e) {
DebugPlugin.logMessage("Problem saving changes to configuration " + currentConfig.getName(), e); //$NON-NLS-1$
}
}
return super.performOk();
}
@Override
protected void performDefaults() {
setErrorMessage(null);
setValid(true);
fOriginalCandidates.clear();
fOriginalCandidates = null;
getViewer().setInput(collectConfigCandidates(getResource()));
fChangedConfigurations.clear();
fDeletedConfigurations.clear();
fViewer.refresh(true, true);
super.performDefaults();
}
/**
* Returns the names of the launch configurations passed in as original input to the tree viewer
* @return the names of the original launch configurations
*/
private Set<String> getConfigurationNames() {
Set<String> names = new HashSet<>();
for(ILaunchConfiguration config : fOriginalCandidates) {
names.add(config.getName());
}
for(ILaunchConfigurationWorkingCopy config : fChangedConfigurations) {
names.add(config.getName());
}
return names;
}
/**
* Returns selected configurations.
*
* @return selected configurations
*/
private ILaunchConfigurationWorkingCopy[] getSelectedConfigurations() {
IStructuredSelection ss = fViewer.getStructuredSelection();
return (ILaunchConfigurationWorkingCopy[]) ss.toList().toArray(new ILaunchConfigurationWorkingCopy[ss.size()]);
}
/**
* Copy the selection
*/
private void handleCopy() {
ILaunchConfigurationWorkingCopy configuration = getSelectedConfigurations()[0];
try {
ILaunchConfigurationWorkingCopy copy = configuration.copy(
((LaunchManager)DebugPlugin.getDefault().getLaunchManager()).generateUniqueLaunchConfigurationNameFrom(configuration.getName(), getConfigurationNames()));
copy.setAttributes(configuration.getAttributes());
fChangedConfigurations.add(copy);
fViewer.add(copy);
fViewer.setSelection(new StructuredSelection(copy));
} catch (CoreException e) {
setErrorMessage(e.getMessage());
}
}
/**
* Delete the selection
*/
private void handleDelete() {
Table table = fViewer.getTable();
int[] indices = table.getSelectionIndices();
Arrays.sort(indices);
ILaunchConfigurationWorkingCopy[] configurations = getSelectedConfigurations();
for (ILaunchConfigurationWorkingCopy configuration : configurations) {
fDeletedConfigurations.add(configuration);
fChangedConfigurations.remove(configuration);
fViewer.remove(configuration);
}
if (indices[0] < table.getItemCount()) {
fViewer.setSelection(new StructuredSelection(table.getItem(indices[0]).getData()));
} else if (table.getItemCount() > 0) {
fViewer.setSelection(new StructuredSelection(table.getItem(table.getItemCount() - 1).getData()));
}
}
/**
* Edit the selection
*/
private void handleEdit() {
ILaunchConfigurationWorkingCopy config = getSelectedConfigurations()[0];
int ret = edit(config, false);
if(ret == IDialogConstants.OK_ID) {
fChangedConfigurations.add(config);
fViewer.refresh(config, true, true);
}
else if(ret == IDialogConstants.ABORT_ID) {
setErrorMessage(MessageFormat.format(DebugPreferencesMessages.RunDebugPropertiesPage_0, new Object[] { config.getName() }));
}
}
/**
* Edits the given configuration as a nested working copy.
* Returns the code from the dialog used to edit the configuration.
*
* @param configuration the configuration working copy to editor
* @param setDefaults whether to set default values in the config
* @return dialog return code - OK or CANCEL
*/
private int edit(ILaunchConfigurationWorkingCopy configuration, boolean setDefaults) {
try {
LaunchConfigurationManager lcm = DebugUIPlugin.getDefault().getLaunchConfigurationManager();
ILaunchGroup group = null;
// bug 208034, we should try modes we know about first then guess
ILaunchConfigurationType type = configuration.getType();
if(type.supportsMode(ILaunchManager.RUN_MODE)) {
group = lcm.getLaunchGroup(type, ILaunchManager.RUN_MODE);
}
else if(type.supportsMode(ILaunchManager.DEBUG_MODE)) {
group = lcm.getLaunchGroup(type, ILaunchManager.DEBUG_MODE);
}
else if(type.supportsMode(ILaunchManager.PROFILE_MODE)) {
group = lcm.getLaunchGroup(type, ILaunchManager.PROFILE_MODE);
}
else {
for (Set<String> modes : type.getSupportedModeCombinations()) {
group = DebugUIPlugin.getDefault().getLaunchConfigurationManager().getLaunchGroup(type, modes);
if(group != null) {
break;
}
}
}
if(group != null) {
return DebugUIPlugin.openLaunchConfigurationPropertiesDialog(getShell(), configuration, group.getIdentifier(), getConfigurationNames(), null, setDefaults);
}
}
catch(CoreException ce) {}
return IDialogConstants.ABORT_ID;
}
/**
* Create a new configuration
*/
private void handleNew() {
final ILaunchConfigurationType[] typeCandidates = collectTypeCandidates();
SelectionDialog dialog = new AbstractDebugListSelectionDialog(getShell()){
@Override
protected String getDialogSettingsId() {
return DebugUIPlugin.getUniqueIdentifier() + ".SELECT_CONFIGURATION_TYPE_DIALOG"; //$NON-NLS-1$
}
@Override
protected Object getViewerInput() {
return typeCandidates;
}
@Override
protected String getHelpContextId() {
return IDebugHelpContextIds.SELECT_CONFIGURATION_TYPE_DIALOG;
}
@Override
protected String getViewerLabel() {
return DebugPreferencesMessages.DefaultLaunchConfigurationsPropertiesPage_12;
}
};
dialog.setTitle(DebugPreferencesMessages.DefaultLaunchConfigurationsPropertiesPage_11);
if (dialog.open() == Window.OK) {
Object[] result = dialog.getResult();
if (result.length == 1) {
ILaunchConfigurationType type = (ILaunchConfigurationType) result[0];
try {
ILaunchConfigurationWorkingCopy wc = type.newInstance(null,
((LaunchManager)DebugPlugin.getDefault().getLaunchManager()).
generateUniqueLaunchConfigurationNameFrom("New_configuration", getConfigurationNames())); //$NON-NLS-1$
int ret = edit(wc, true);
if (ret == Window.OK) {
fChangedConfigurations.add(wc);
fViewer.add(wc);
fViewer.setSelection(new StructuredSelection(wc));
}
else if(ret == IDialogConstants.ABORT_ID) {
setErrorMessage(MessageFormat.format(DebugPreferencesMessages.RunDebugPropertiesPage_0, new Object[] { wc.getName() }));
}
} catch (CoreException e) {
setErrorMessage(e.getMessage());
}
}
}
}
}