blob: cef59f496054d47d0de2ec5041c46e70e2e55b82 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 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.internal.ui.launchConfigurations;
import com.ibm.icu.text.MessageFormat;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
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.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
import org.eclipse.debug.internal.ui.SWTUtil;
import org.eclipse.debug.internal.ui.preferences.PerspectivePreferencePage;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.ILaunchConfigurationDialog;
import org.eclipse.debug.ui.ILaunchConfigurationTab;
import org.eclipse.debug.ui.ILaunchConfigurationTabGroup;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.custom.ViewForm;
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.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
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.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.PlatformUI;
/**
* A viewer that displays tabs for a launch configuration, with apply and revert
* buttons.
*/
public class LaunchConfigurationTabGroupViewer extends Viewer {
private final String EMPTY_STRING = ""; //$NON-NLS-1$
/**
* Containing launch dialog
*/
private ILaunchConfigurationDialog fDialog;
/**
* The this viewer's input
*/
private Object fInput;
/**
* The launch configuration (original) being edited
*/
private ILaunchConfiguration fOriginal;
/**
* The working copy of the original
*/
private ILaunchConfigurationWorkingCopy fWorkingCopy;
/**
* This view's control, which contains a composite area of controls
*/
private Composite fViewerControl;
/**
* The composite which is hidden/displayed as tabs are required.
*/
private Composite fVisibleArea;
/**
* Name label widget
*/
private Label fNameLabel;
/**
* Name text widget
*/
private Text fNameWidget;
/**
* Composite containing the launch config tab widgets
*/
private Composite fTabComposite;
/**
* Tab folder
*/
private CTabFolder fTabFolder;
/**
* The current tab group being displayed
*/
private ILaunchConfigurationTabGroup fTabGroup;
/**
* The type of config tabs are currently displayed
* for
*/
private ILaunchConfigurationType fTabType;
/**
* Index of the active tab
*/
private int fCurrentTabIndex = -1;
/**
* Apply & Revert buttons
*/
private Button fApplyButton;
private Button fRevertButton;
/**
* Whether tabs are currently being disposed or initialized
*/
private boolean fDisposingTabs = false;
private boolean fInitializingTabs = false;
/**
* Controls when the redraw flag is set on the visible area
*/
private boolean fRedraw = true;
/**
* The description of the currently selected launch configuration or
* launch configuration type or <code>null</code> if none.
*/
private String fDescription = null;
/**
* A placeholder for switching between the tabs for a config and the getting started tab
* @since 3.2
*/
private Composite fTabPlaceHolder = null;
/**
* A new composite replacing the perspectives tab
* @since 3.2
*/
private Composite fGettingStarted = null;
private ViewForm fViewform;
/**
* Constructs a viewer in the given composite, contained by the given
* launch configuration dialog.
*
* @param parent composite containing this viewer
* @param dialog containing launch configuration dialog
*/
public LaunchConfigurationTabGroupViewer(Composite parent, ILaunchConfigurationDialog dialog) {
super();
fDialog = dialog;
createControl(parent);
}
/**
* Cleanup
*/
public void dispose() {
disposeTabGroup();
}
/**
* Dispose the active tab group, if any.
*/
protected void disposeTabGroup() {
if (getTabGroup() != null) {
getTabGroup().dispose();
fTabGroup = null;
fTabType = null;
}
}
/**
* Creates this viewer's control This area displays the name of the launch
* configuration currently being edited, as well as a tab folder of tabs
* that are applicable to the launch configuration.
*
* @return the composite used for launch configuration editing
*/
private void createControl(Composite parent) {
fViewerControl = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
fViewerControl.setLayout(layout);
GridData gd = new GridData(GridData.FILL_BOTH);
fViewerControl.setLayoutData(gd);
fViewform = new ViewForm(fViewerControl, SWT.FLAT | SWT.BORDER);
layout = new GridLayout(1, false);
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
fViewform.setLayout(layout);
gd = new GridData(GridData.FILL_BOTH);
fViewform.setLayoutData(gd);
fVisibleArea = fViewform;
fViewform.setTopLeft(null);
Composite mainComp = new Composite(fViewform, SWT.FLAT);
layout = new GridLayout(1, false);
layout.verticalSpacing = 0;
layout.horizontalSpacing = 0;
mainComp.setLayout(layout);
fViewform.setContent(mainComp);
fTabPlaceHolder = new Composite(mainComp, SWT.NONE);
fTabPlaceHolder.setLayout(new StackLayout());
gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = 2;
fTabPlaceHolder.setLayoutData(gd);
fGettingStarted = new Composite(fTabPlaceHolder, SWT.NONE);
fGettingStarted.setLayout(new GridLayout());
gd = new GridData(GridData.FILL_BOTH);
fGettingStarted.setLayoutData(gd);
createGettingStarted(fGettingStarted);
fTabComposite = new Composite(fTabPlaceHolder, SWT.NONE);
layout = new GridLayout(2, false);
layout.verticalSpacing = 10;
layout.horizontalSpacing = 5;
fTabComposite.setLayout(layout);
gd = new GridData(GridData.FILL_BOTH);
fTabComposite.setLayoutData(gd);
fNameLabel = new Label(fTabComposite, SWT.HORIZONTAL | SWT.LEFT);
fNameLabel.setText(LaunchConfigurationsMessages.LaunchConfigurationDialog__Name__16);
fNameLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
fNameWidget = new Text(fTabComposite, SWT.SINGLE | SWT.BORDER);
fNameWidget.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fNameWidget.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
handleNameModified();
}
}
);
createTabFolder(fTabComposite);
Composite buttonComp = new Composite(mainComp, SWT.NONE);
GridLayout buttonCompLayout = new GridLayout();
buttonCompLayout.numColumns = 2;
buttonComp.setLayout(buttonCompLayout);
gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
gd.horizontalSpan = 2;
buttonComp.setLayoutData(gd);
fApplyButton = new Button(buttonComp, SWT.PUSH);
fApplyButton.setText(LaunchConfigurationsMessages.LaunchConfigurationDialog__Apply_17);
gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
fApplyButton.setLayoutData(gd);
SWTUtil.setButtonDimensionHint(fApplyButton);
fApplyButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent evt) {
handleApplyPressed();
}
});
fRevertButton = new Button(buttonComp, SWT.PUSH);
fRevertButton.setText(LaunchConfigurationsMessages.LaunchConfigurationDialog_Revert_2);
gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
fRevertButton.setLayoutData(gd);
SWTUtil.setButtonDimensionHint(fRevertButton);
fRevertButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent evt) {
handleRevertPressed();
}
});
Dialog.applyDialogFont(parent);
}
/**
* Simple method to create a spacer in the page
*
* @param composite the composite to add the spacer to
* @param columnSpan the amount of space for the spacer
* @since 3.2
*/
protected void createSpacer(Composite composite, int columnSpan) {
Label label = new Label(composite, SWT.NONE);
GridData gd = new GridData();
gd.horizontalSpan = columnSpan;
label.setLayoutData(gd);
}
/**
* Creates some help text for the tab group launch types
* @param parent thep arent composite
* @since 3.2
*/
private void createGettingStarted(Composite parent) {
Font font = parent.getFont();
GridData gd = null;
createWrapLabel(parent, null, LaunchConfigurationsMessages.LaunchConfigurationTabGroupViewer_1);
createWrapLabel(parent, DebugUITools.getImage(IInternalDebugUIConstants.IMG_ELCL_NEW_CONFIG),
LaunchConfigurationsMessages.LaunchConfigurationTabGroupViewer_2);
createWrapLabel(parent, DebugUITools.getImage(IInternalDebugUIConstants.IMG_ELCL_DUPLICATE_CONFIG),
LaunchConfigurationsMessages.LaunchConfigurationTabGroupViewer_6);
createWrapLabel(parent, DebugUITools.getImage(IInternalDebugUIConstants.IMG_ELCL_DELETE_CONFIG),
LaunchConfigurationsMessages.LaunchConfigurationTabGroupViewer_4);
createWrapLabel(parent, DebugUITools.getImage(IInternalDebugUIConstants.IMG_ELCL_FILTER_CONFIGS),
LaunchConfigurationsMessages.LaunchConfigurationTabGroupViewer_8);
createWrapLabel(parent, DebugUITools.getImage(IInternalDebugUIConstants.IMG_OVR_TRANSPARENT),
LaunchConfigurationsMessages.LaunchConfigurationTabGroupViewer_3);
createSpacer(parent, 2);
Link link = new Link(parent, SWT.LEFT | SWT.WRAP);
link.setText(LaunchConfigurationsMessages.LaunchConfigurationTabGroupViewer_5);
link.setFont(font);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint = parent.getBounds().width - 30;
link.setLayoutData(gd);
link.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
SWTUtil.showPreferencePage("org.eclipse.debug.ui.PerspectivePreferencePage", new PerspectivePreferencePage()); //$NON-NLS-1$
}
public void widgetDefaultSelected(SelectionEvent e) {}
});
}
/**
* Create a label on the given parent that wraps text.
*
* @param parent
* @param text
*/
private void createWrapLabel(Composite parent, Image image, String text) {
CLabel lbl = new CLabel(parent, SWT.NONE | SWT.WRAP);
lbl.setImage(image);
lbl.setFont(parent.getFont());
lbl.setText(text);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint = parent.getBounds().width - 30;
lbl.setLayoutData(gd);
}
/**
* Creates the tab folder for displaying config instances
* @param parent
*/
private void createTabFolder(Composite parent) {
if (fTabFolder == null) {
Display display = getShell().getDisplay();
Color c1 = display.getSystemColor(SWT.COLOR_TITLE_BACKGROUND),
c2 = display.getSystemColor(SWT.COLOR_TITLE_BACKGROUND_GRADIENT);
fTabFolder = new CTabFolder(parent, SWT.NO_REDRAW_RESIZE | SWT.NO_TRIM | SWT.FLAT);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = 2;
fTabFolder.setSelectionBackground(new Color[] {c1, c2}, new int[] {100}, true);
fTabFolder.setSelectionForeground(getShell().getDisplay().getSystemColor(SWT.COLOR_TITLE_FOREGROUND));
fTabFolder.setSimple(PlatformUI.getPreferenceStore().getBoolean(IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS));
fTabFolder.setLayoutData(gd);
fTabFolder.setBorderVisible(true);
fTabFolder.setFont(parent.getFont());
fTabFolder.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
if (!fInitializingTabs) {
handleTabSelected();
}
}
});
}
}
/**
* Returns the apply button
*/
protected Button getApplyButton() {
return fApplyButton;
}
/**
* Returns the revert button
*/
protected Button getRevertButton() {
return fRevertButton;
}
/**
* Sets the tab folder
*/
protected CTabFolder getTabFolder() {
return fTabFolder;
}
/**
* Sets the current name
*/
public void setName(String name) {
if (getWorkingCopy() != null) {
if (name == null) {
name = EMPTY_STRING;
}
fNameWidget.setText(name.trim());
refreshStatus();
}
}
/**
* @see org.eclipse.jface.viewers.Viewer#getControl()
*/
public Control getControl() {
return fViewerControl;
}
/**
* Returns the shell this viewer is contained in.
*/
protected Shell getShell() {
return getControl().getShell();
}
/**
* @see org.eclipse.jface.viewers.IInputProvider#getInput()
*/
public Object getInput() {
return fInput;
}
/**
* @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
*/
public ISelection getSelection() {
if (getActiveTab() == null) {
return new StructuredSelection();
}
return new StructuredSelection(getActiveTab());
}
/**
* @see org.eclipse.jface.viewers.Viewer#refresh()
*/
public void refresh() {
if (fInitializingTabs) {
return;
}
ILaunchConfigurationTab[] tabs = getTabs();
if (!fInitializingTabs && tabs != null) {
// update the working copy from the active tab
getActiveTab().performApply(getWorkingCopy());
updateButtons();
// update error ticks
for (int i = 0; i < tabs.length; i++) {
ILaunchConfigurationTab tab = tabs[i];
tab.isValid(getWorkingCopy());
boolean error = tab.getErrorMessage() != null;
CTabItem item = fTabFolder.getItem(i);
setTabIcon(item, error, tab);
}
}
}
/**
* updates the button states
*/
private void updateButtons() {
boolean dirty = isDirty();
fApplyButton.setEnabled(dirty && canSave());
fRevertButton.setEnabled(dirty);
}
/**
* Set the specified tab item's icon to an error icon if <code>error</code> is true,
* or a transparent icon of the same size otherwise.
*/
private void setTabIcon(CTabItem tabItem, boolean error, ILaunchConfigurationTab tab) {
Image image = null;
if (error) {
image = DebugUIPlugin.getDefault().getLaunchConfigurationManager().getErrorTabImage(tab);
} else {
image = tab.getImage();
}
tabItem.setImage(image);
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.Viewer#setInput(java.lang.Object)
*/
public void setInput(Object input) {
if (input == null) {
if (fInput == null) {
return;
}
inputChanged(input);
} else {
if (!input.equals(fInput)) {
inputChanged(input);
}
}
}
/**
* The input has changed to the given object, possibly <code>null</code>.
*
* @param input the new input, possibly <code>null</code>
*/
protected void inputChanged(Object input) {
fInput = input;
Runnable r = new Runnable() {
public void run() {
try {
if (fInput instanceof ILaunchConfiguration) {
ILaunchConfiguration configuration = (ILaunchConfiguration)fInput;
fOriginal = configuration;
fWorkingCopy = configuration.getWorkingCopy();
displayInstanceTabs();
} else if (fInput instanceof ILaunchConfigurationType) {
fDescription = getDescription((ILaunchConfigurationType)fInput);
setNoInput();
refreshStatus();
} else {
setNoInput();
refreshStatus();
}
setRedraw(true);
} catch (CoreException ce) {
errorDialog(ce);
setNoInput();
setRedraw(true);
}
}
};
BusyIndicator.showWhile(getShell().getDisplay(), r);
}
/**
* Sets the tab group viewer to have no input, this is the case when null is passed as an input type
* Setting no input is equivalent to resetting all items, clearing any messages and showing the 'getting started' pane
* @since 3.2
*/
private void setNoInput() {
fOriginal = null;
fWorkingCopy = null;
disposeExistingTabs();
updateButtons();
updateVisibleControls(false);
ILaunchConfigurationDialog lcd = getLaunchConfigurationDialog();
if(lcd instanceof LaunchConfigurationsDialog) {
if(((LaunchConfigurationsDialog)lcd).isTreeSelectionEmpty()) {
fDescription = EMPTY_STRING;
}
}
}
/**
* Updates the visibility of controls based on the status provided
* @param visible the visibility status to be applied to the controls
*/
private void updateVisibleControls(boolean visible) {
fApplyButton.setVisible(visible);
fRevertButton.setVisible(visible);
if(visible) {
((StackLayout)fTabPlaceHolder.getLayout()).topControl = fTabComposite;
fTabComposite.layout();
}
else {
((StackLayout)fTabPlaceHolder.getLayout()).topControl = fGettingStarted;
}
fTabPlaceHolder.layout(true);
}
/**
* sets the current widget focus to the 'Name' widget
*/
protected void setFocusOnName() {
fNameWidget.setFocus();
}
/**
* Sets if the
* @param b
*/
private void setRedraw(boolean b) {
if (fRedraw != b) {
fRedraw = b;
fVisibleArea.setRedraw(fRedraw);
}
}
/**
* Displays tabs for the current working copy
*/
protected void displayInstanceTabs() {
// Turn on initializing flag to ignore message updates
fInitializingTabs = true;
ILaunchConfigurationType type = null;
try {
type = getWorkingCopy().getType();
showInstanceTabsFor(type);
} catch (CoreException e) {
errorDialog(e);
fInitializingTabs = false;
return;
}
// show the name area
updateVisibleControls(true);
// Update the name field before to avoid verify error
fNameWidget.setText(getWorkingCopy().getName());
// Retrieve the current tab group. If there is none, clean up and leave
ILaunchConfigurationTabGroup tabGroup = getTabGroup();
if (tabGroup == null) {
IStatus status = new Status(IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(), 0, MessageFormat.format(LaunchConfigurationsMessages.LaunchConfigurationTabGroupViewer_No_tabs_defined_for_launch_configuration_type__0__1, new String[]{type.getName()}), null);
CoreException e = new CoreException(status);
errorDialog(e);
fInitializingTabs = false;
return;
}
// Update the tabs with the new working copy
tabGroup.initializeFrom(getWorkingCopy());
// Update the name field after in case client changed it
fNameWidget.setText(getWorkingCopy().getName());
fCurrentTabIndex = fTabFolder.getSelectionIndex();
// Turn off initializing flag to update message
fInitializingTabs = false;
if (!fVisibleArea.isVisible()) {
fVisibleArea.setVisible(true);
}
refreshStatus();
}
/**
* Populate the tabs in the configuration edit area to be appropriate to the current
* launch configuration type.
*/
private void showInstanceTabsFor(ILaunchConfigurationType configType) {
// Don't do any work if the current tabs are for the current config type
if (fTabType != null && fTabType.equals(configType)) {
return;
}
// try to keep on same tab
Class tabKind = null;
if (getActiveTab() != null) {
tabKind = getActiveTab().getClass();
}
// Build the new tabs
ILaunchConfigurationTabGroup group = null;
try {
group = createGroup(configType);
} catch (CoreException ce) {
DebugUIPlugin.errorDialog(getShell(), LaunchConfigurationsMessages.LaunchConfigurationDialog_Error_19, LaunchConfigurationsMessages.LaunchConfigurationDialog_Exception_occurred_creating_launch_configuration_tabs_27,ce); //
return;
}
showTabsFor(group);
fTabGroup = group;
fTabType = configType;
// select same tab as before, if possible
ILaunchConfigurationTab[] tabs = getTabs();
//set the default tab as the first one
setActiveTab(tabs[0]);
for (int i = 0; i < tabs.length; i++) {
ILaunchConfigurationTab tab = tabs[i];
if (tab.getClass().equals(tabKind)) {
setActiveTab(tab);
break;
}
}
fDescription = getDescription(configType);
}
/**
* Returns the description of the given configuration type
* in the current mode or <code>null</code> if none.
*
* @param configType the config type
* @return the description of the given configuration type or <code>null</code>
*/
private String getDescription(ILaunchConfigurationType configType) {
String description = null;
if(configType != null) {
String mode = fDialog.getMode();
description = LaunchConfigurationPresentationManager.getDefault().getDescription(configType, mode);
}
if (description == null)
description = EMPTY_STRING;
return description;
}
/**
* Create the tabs in the configuration edit area for the given tab group.
*/
private void showTabsFor(ILaunchConfigurationTabGroup tabGroup) {
// turn off redraw
setRedraw(false);
// Dispose the current tabs
disposeExistingTabs();
fTabGroup = tabGroup;
// Create the Control for each tab
ILaunchConfigurationTab[] tabs = tabGroup.getTabs();
CTabItem tab = null;
String name = EMPTY_STRING;
for (int i = 0; i < tabs.length; i++) {
tab = new CTabItem(fTabFolder, SWT.BORDER);
name = tabs[i].getName();
if (name == null) {
name = LaunchConfigurationsMessages.LaunchConfigurationDialog_unspecified_28;
}
tab.setText(name);
Image image = tabs[i].getImage();
tab.setImage(image);
tabs[i].createControl(tab.getParent());
Control control = tabs[i].getControl();
if (control != null) {
tab.setControl(control);
}
}
}
/**
* Returns tab group for the given type of launch configuration.
* Tabs are initialized to be contained in this dialog.
*
* @exception CoreException if unable to instantiate a tab group
*/
protected ILaunchConfigurationTabGroup createGroup(final ILaunchConfigurationType configType) throws CoreException {
// Use a final Object array to store the tab group and any exception that
// results from the Runnable
final Object[] finalArray = new Object[2];
Runnable runnable = new Runnable() {
public void run() {
ILaunchConfigurationTabGroup tabGroup = null;
try {
tabGroup = LaunchConfigurationPresentationManager.getDefault().getTabGroup(configType, getLaunchConfigurationDialog().getMode());
finalArray[0] = tabGroup;
} catch (CoreException ce) {
finalArray[1] = ce;
return;
}
tabGroup.createTabs(getLaunchConfigurationDialog(), getLaunchConfigurationDialog().getMode());
ILaunchConfigurationTab[] tabs = tabGroup.getTabs();
for (int i = 0; i < tabs.length; i++) {
tabs[i].setLaunchConfigurationDialog(getLaunchConfigurationDialog());
}
}
};
// Creating the tabs can result in plugin loading, so we show the busy cursor
BusyIndicator.showWhile(getControl().getDisplay(), runnable);
// Re-throw any CoreException if there was one
if (finalArray[1] != null) {
throw (CoreException)finalArray[1];
}
// Otherwise return the tab group
return (ILaunchConfigurationTabGroup)finalArray[0];
}
/**
* @see org.eclipse.jface.viewers.Viewer#setSelection(org.eclipse.jface.viewers.ISelection, boolean)
*/
public void setSelection(ISelection selection, boolean reveal) {
if (getWorkingCopy() != null) {
if (selection instanceof IStructuredSelection) {
IStructuredSelection structuredSelection = (IStructuredSelection)selection;
Object object = structuredSelection.getFirstElement();
if (object instanceof ILaunchConfigurationTab) {
ILaunchConfigurationTab[] tabs = getTabs();
for (int i = 0; i < tabs.length; i++) {
ILaunchConfigurationTab tab = tabs[i];
if (tab.equals(object)) {
fCurrentTabIndex = i;
fTabFolder.setSelection(i);
}
return;
}
}
}
}
}
/**
* Returns the tabs currently being displayed, or
* <code>null</code> if none.
*
* @return currently displayed tabs, or <code>null</code>
*/
public ILaunchConfigurationTab[] getTabs() {
if (getTabGroup() != null) {
return getTabGroup().getTabs();
}
return null;
}
/**
* Returns the currently active <code>ILaunchConfigurationTab</code>
* being displayed, or <code>null</code> if there is none.
*
* @return currently active <code>ILaunchConfigurationTab</code>, or <code>null</code>.
*/
public ILaunchConfigurationTab getActiveTab() {
ILaunchConfigurationTab[] tabs = getTabs();
if (fTabFolder != null && tabs != null) {
int pageIndex = fTabFolder.getSelectionIndex();
if (pageIndex >= 0) {
return tabs[pageIndex];
}
}
return null;
}
/**
* Returns whether the launch configuration being edited is dirty (i.e.
* needs saving)
*
* @return whether the launch configuration being edited needs saving
*/
public boolean isDirty() {
ILaunchConfigurationWorkingCopy workingCopy = getWorkingCopy();
if (workingCopy == null) {
return false;
}
// Working copy hasn't been saved
if (workingCopy.getOriginal() == null) {
return true;
}
ILaunchConfiguration original = getOriginal();
return !original.contentsEqual(workingCopy);
}
/**
* Update apply & revert buttons, as well as buttons and message on the
* launch config dialog.
*/
protected void refreshStatus() {
if (!fInitializingTabs) {
getLaunchConfigurationDialog().updateButtons();
getLaunchConfigurationDialog().updateMessage();
}
}
/**
* Returns the containing launch dialog
*/
protected ILaunchConfigurationDialog getLaunchConfigurationDialog() {
return fDialog;
}
/**
* Returns the original launch configuration being edited, possibly
* <code>null</code>.
*
* @return ILaunchConfiguration
*/
protected ILaunchConfiguration getOriginal() {
return fOriginal;
}
/**
* Returns the working copy used to edit the original, possibly
* <code>null</code>.
*/
protected ILaunchConfigurationWorkingCopy getWorkingCopy() {
return fWorkingCopy;
}
/**
* Return whether the current configuration can be saved.
* <p>
* Note this is NOT the same thing as the config simply being valid. It
* is possible to save a config that does not validate. This method
* determines whether the config can be saved without causing a serious
* error. For example, a shared config that has no specified location would
* cause this method to return <code>false</code>.
* </p>
*/
public boolean canSave() {
if (fInitializingTabs) {
return false;
}
// First make sure that name doesn't prevent saving the config
try {
verifyName();
} catch (CoreException ce) {
return false;
}
// Next, make sure none of the tabs object to saving the config
ILaunchConfigurationTab[] tabs = getTabs();
if (tabs == null) {
return false;
}
for (int i = 0; i < tabs.length; i++) {
if (!tabs[i].canSave()) {
return false;
}
}
return true;
}
/**
* @see ILaunchConfigurationDialog#canLaunch()
*/
public boolean canLaunch() {
if(fInitializingTabs) {
return false;
}
if (getWorkingCopy() == null) {
return false;
}
try {
verifyName();
} catch (CoreException e) {
return false;
}
ILaunchConfigurationTab[] tabs = getTabs();
if (tabs == null) {
return false;
}
for (int i = 0; i < tabs.length; i++) {
if (!tabs[i].isValid(getWorkingCopy())) {
return false;
}
}
return true;
}
/**
* Returns the current error message or <code>null</code> if none.
*/
public String getErrorMesssage() {
if (fInitializingTabs) {
return null;
}
if (getWorkingCopy() == null) {
return null;
}
try {
verifyName();
} catch (CoreException ce) {
return ce.getStatus().getMessage();
}
String message = null;
ILaunchConfigurationTab activeTab = getActiveTab();
if (activeTab == null) {
return null;
}
message = activeTab.getErrorMessage();
if (message != null) {
return message;
}
ILaunchConfigurationTab[] allTabs = getTabs();
for (int i = 0; i < allTabs.length; i++) {
ILaunchConfigurationTab tab = allTabs[i];
if (tab == activeTab) {
continue;
}
message = tab.getErrorMessage();
if (message != null) {
StringBuffer temp= new StringBuffer();
temp.append('[');
temp.append(DebugUIPlugin.removeAccelerators(tab.getName()));
temp.append("]: "); //$NON-NLS-1$
temp.append(message);
return temp.toString();
}
}
return null;
}
/**
* Returns the current message or <code>null</code> if none.
* @return Returns an appropriate message for display to user. The message returned will be:
* The message defined by the visible tab,
* or The tab group description for the particular launch mode,
* or The generic tab group description,
* or <code>null</code> if no message is defined
*/
public String getMessage() {
if (fInitializingTabs) {
return null;
}
String message = fDescription;
ILaunchConfigurationTab tab = getActiveTab();
if (tab != null) {
String tabMessage = tab.getMessage();
if (tabMessage != null) {
message = tabMessage;
}
}
return message;
}
/**
* Verify that the launch configuration name is valid.
*/
protected void verifyName() throws CoreException {
if (fNameWidget.isVisible()) {
String currentName = fNameWidget.getText().trim();
// If there is no name, complain
if (currentName.length() < 1) {
throw new CoreException(new Status(IStatus.ERROR,
DebugUIPlugin.getUniqueIdentifier(),
0,
LaunchConfigurationsMessages.LaunchConfigurationDialog_Name_required_for_launch_configuration_11,
null));
}
// See if name contains any 'illegal' characters
IStatus status = ResourcesPlugin.getWorkspace().validateName(currentName, IResource.FILE);
if (status.getCode() != IStatus.OK) {
throw new CoreException(new Status(IStatus.ERROR,
DebugUIPlugin.getUniqueIdentifier(),
0,
status.getMessage(),
null));
}
// See if name contains any characters that we deem illegal.
// '@' and '&' are disallowed because they corrupt menu items.
char[] disallowedChars = new char[] { '@', '&' };
for (int i = 0; i < disallowedChars.length; i++) {
char c = disallowedChars[i];
if (currentName.indexOf(c) > -1) {
throw new CoreException(new Status(IStatus.ERROR,
DebugUIPlugin.getUniqueIdentifier(),
0,
MessageFormat.format(LaunchConfigurationsMessages.LaunchConfigurationTabGroupViewer_0, new String[] { new String(new char[] {c}), currentName }),
null));
}
}
// Otherwise, if there's already a config with the same name, complain
if (!getOriginal().getName().equals(currentName)) {
if (DebugPlugin.getDefault().getLaunchManager().isExistingLaunchConfigurationName(currentName)) {
throw new CoreException(new Status(IStatus.ERROR,
DebugUIPlugin.getUniqueIdentifier(),
0,
LaunchConfigurationsMessages.LaunchConfigurationDialog_Launch_configuration_already_exists_with_this_name_12,
null));
}
}
}
}
/**
* Remove the existing tabs that are showing
*/
private void disposeExistingTabs() {
fDisposingTabs = true;
fTabFolder.dispose();
fTabFolder = null;
createTabFolder(fTabComposite);
disposeTabGroup();
fDisposingTabs = false;
}
/**
* Returns the current tab group
*
* @return the current tab group, or <code>null</code> if none
*/
public ILaunchConfigurationTabGroup getTabGroup() {
return fTabGroup;
}
/**
* Notification that a tab has been selected
*
* Disallow tab changing when the current tab is invalid.
* Update the config from the tab being left, and refresh
* the tab being entered.
*/
protected void handleTabSelected() {
if (fDisposingTabs || fInitializingTabs) {
return;
}
ILaunchConfigurationTab[] tabs = getTabs();
if (fCurrentTabIndex == fTabFolder.getSelectionIndex() || tabs == null || tabs.length == 0 || fCurrentTabIndex > (tabs.length - 1)) {
return;
}
if (fCurrentTabIndex != -1) {
ILaunchConfigurationTab tab = tabs[fCurrentTabIndex];
ILaunchConfigurationWorkingCopy wc = getWorkingCopy();
if (wc != null) {
tab.deactivated(wc);
getActiveTab().activated(wc);
}
}
fCurrentTabIndex = fTabFolder.getSelectionIndex();
SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection());
fireSelectionChanged(event);
}
/**
* Notification the name field has been modified
*/
protected void handleNameModified() {
getWorkingCopy().rename(fNameWidget.getText().trim());
refreshStatus();
}
/**
* Notification that the 'Apply' button has been pressed
*/
protected void handleApplyPressed() {
try {
// trim name
Text widget = fNameWidget;
String name = widget.getText();
String trimmed = name.trim();
// update launch config
fInitializingTabs = true;
if (!name.equals(trimmed)) {
widget.setText(trimmed);
}
getWorkingCopy().rename(trimmed);
getTabGroup().performApply(getWorkingCopy());
fInitializingTabs = false;
if (isDirty()) {
getWorkingCopy().doSave();
}
updateButtons();
} catch (CoreException e) {
DebugUIPlugin.errorDialog(getShell(), LaunchConfigurationsMessages.LaunchConfigurationDialog_Launch_Configuration_Error_46, LaunchConfigurationsMessages.LaunchConfigurationDialog_Exception_occurred_while_saving_launch_configuration_47, e); //
return;
}
}
/**
* Notification that the 'Revert' button has been pressed
*/
protected void handleRevertPressed() {
inputChanged(getOriginal());
}
/**
* Show an error dialog on the given exception.
*
* @param exception
*/
protected void errorDialog(CoreException exception) {
ErrorDialog.openError(getShell(), null, null, exception.getStatus());
}
/**
* Sets the displayed tab to the given tab. Has no effect if the specified
* tab is not one of the tabs being displayed in the dialog currently.
*
* @param tab the tab to display/activate
*/
public void setActiveTab(ILaunchConfigurationTab tab) {
ILaunchConfigurationTab[] tabs = getTabs();
for (int i = 0; i < tabs.length; i++) {
ILaunchConfigurationTab configurationTab = tabs[i];
if (configurationTab.equals(tab)) {
setActiveTab(i);
return;
}
}
}
/**
* Sets the displayed tab to the tab with the given index. Has no effect if
* the specified index is not within the limits of the tabs returned by
* <code>getTabs()</code>.
*
* @param index the index of the tab to dispay
*/
public void setActiveTab(int index) {
ILaunchConfigurationTab[] tabs = getTabs();
if (index >= 0 && index < tabs.length) {
fTabFolder.setSelection(index);
handleTabSelected();
}
}
}