Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: 971e244763f2e40b793339eb5fb64bfd8132d1fa (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                                                                

                                                                   






                                                                                 

                                                           





























                                                              
                                     
                                      
                                      










































                                                                                




                                                                        




                                 






























                                                             
                                 










                                                                   




                                                                   





                                                                            











                                                                                                       


                  
                               
                                  
         










                                                








                                                                                  
                                             

                                                                 
                                               
                                                 
                                                
                                                          
                                                               
                                                 









                                                                              
 

                                                                                                                                
                                                      

                                             
                
                                                                             

                                                            
                                       









                                                                       
                                                              



                                         
                                                                   







                                                                      
                                               
 
                                                                          










                                                                                                                                      
                                               










                                                                                                                                        
                                                








                                                                               





















                                                                            






























                                                     
                                            




























                                                             




































                                                                           



                                           




                                                                      
                                             


                                                                      
                                                              





                                                                              





                                                                







                                                                                              
                                                                                                                 





























                                                                                 

                                             



                                                                                                                  
                                                                                               

                                                                                                
                                                                                                                                                                      
                                                                           
                                                                                               


                                                                    
                                         




                                                            
                                 
                         

                                                                    

         






                                                                





                                                            


                                                     
                                              





                                                                      
                                                  





                                                   


                                             





                                                                                        
                                                                                                                                                                                                                                                                                                                    










                                                                        

                                                                      


                                                               
                

                                                          
                 
                



                                                













































                                                                                                                                                                                                                                                                                                                    


                                                    



                                                


                                                                                            
                                                                               

                                                                                        
                                                                                                                                 


                               



                                                          




                                                                                                                                                                                                                                                                                                         


                                       

                                                          
                





















                                                                                                                                                 














                                                                                                                                

                                                                 











                                                                                             

                                  







                                                                    













                                                                                                                                        
 















                                                                                                                            
                                                                                                                                                                         
































































































                                                                                                                              








                                                                               



                                                                       




















































                                                                                   


                                           























                                                                               



                                          



                                                                
























                                                                          



                                           













                                                                   











                                                                 

                                                        





                                                                                 



















                                                                                                                    




                                                                                                    
           
                                    



                                           

                                              
                                                             




                                                             
                 

                               





                                                              














                                                                                                                                                                                                                                     
                                                                                 
                                                                                                                                             
                                                                                                           
                                                                                                                             

                                                                                                                




                                                                                                        
                                                                                                                                                     




                                                                                                                                                                                                                                                         
























                                                                
                                               
                                  































































                                                                                                                                                         

                                                             










                                                                                              
                                                                          
                                








                                                                

                                                       


                                                  


                                                        




                                                                     


                                                          
                                        



                                                                                                                                                                                                                                                                                                                             





                                                                 




                                                                


                






                                                                                     







                                                          































                                                                                   
 
/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.debug.internal.ui.launchConfigurations;


import java.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.core.ILaunchManager;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.SWTUtil;
import org.eclipse.debug.ui.ILaunchConfigurationDialog;
import org.eclipse.debug.ui.ILaunchConfigurationTab;
import org.eclipse.debug.ui.ILaunchConfigurationTabGroup;
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.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.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;

/**
 * A viewer that displays tabs for a launch configuration, with apply and revert
 * buttons.
 */
public class LaunchConfigurationTabGroupViewer extends Viewer {
	
	/**
	 * 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 TabFolder 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;

	/**
	 * 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();
			setTabGroup(null);
			setTabType(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) {
		Font font = parent.getFont();
		fViewerControl = new Composite(parent, SWT.NONE);
		GridLayout outerCompLayout = new GridLayout();
		outerCompLayout.numColumns = 1;
		outerCompLayout.marginHeight = 0;
		outerCompLayout.marginWidth = 0;
		fViewerControl.setLayout(outerCompLayout);
		GridData gd = new GridData(GridData.FILL_BOTH);
		fViewerControl.setLayoutData(gd);
		
		Composite container = new Composite(fViewerControl, SWT.NONE);
		outerCompLayout = new GridLayout();
		outerCompLayout.numColumns = 2;
		outerCompLayout.marginHeight = 0;
		outerCompLayout.marginWidth = 5;
		container.setLayout(outerCompLayout);
		gd = new GridData(GridData.FILL_BOTH);
		container.setLayoutData(gd);
		setVisibleArea(container);

		fNameLabel = new Label(container, SWT.HORIZONTAL | SWT.LEFT);
		fNameLabel.setText(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.&Name__16")); //$NON-NLS-1$
		gd = new GridData(GridData.BEGINNING);
		fNameLabel.setLayoutData(gd);
		fNameLabel.setFont(font);
		
		Text nameText = new Text(container, SWT.SINGLE | SWT.BORDER);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		nameText.setLayoutData(gd);
		nameText.setFont(font);
		setNameWidget(nameText);

		getNameWidget().addModifyListener(
			new ModifyListener() {
				public void modifyText(ModifyEvent e) {
					handleNameModified();
				}
			}
		);

		Label spacer = new Label(container, SWT.NONE);
		gd = new GridData();
		gd.horizontalSpan = 2;
		spacer.setLayoutData(gd);

		fTabComposite = new Composite(container, SWT.NONE);
		GridLayout outerTabCompositeLayout = new GridLayout();
		outerTabCompositeLayout.marginHeight = 0;
		outerTabCompositeLayout.marginWidth = 0;
		fTabComposite.setLayout(outerTabCompositeLayout);
		gd = new GridData(GridData.FILL_BOTH);
		gd.horizontalSpan = 2;
		fTabComposite.setLayoutData(gd);

		createTabFolder(fTabComposite);

		Composite buttonComp = new Composite(container, 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);

		setApplyButton(new Button(buttonComp, SWT.PUSH));
		getApplyButton().setText(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.&Apply_17")); //$NON-NLS-1$
		gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
		getApplyButton().setLayoutData(gd);
		getApplyButton().setFont(font);
		SWTUtil.setButtonDimensionHint(getApplyButton());
		getApplyButton().addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent evt) {
				handleApplyPressed();
			}
		});

		setRevertButton(new Button(buttonComp, SWT.PUSH));
		getRevertButton().setText(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Revert_2"));   //$NON-NLS-1$
		gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
		getRevertButton().setLayoutData(gd);
		getRevertButton().setFont(font);
		SWTUtil.setButtonDimensionHint(getRevertButton());
		getRevertButton().addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent evt) {
				handleRevertPressed();
			}
		});

	}
	
	private void createTabFolder(Composite parent) {
		Point size = null;
		if (fTabFolder != null) {
			size = fTabFolder.getSize();
			fTabFolder.dispose();
		}
		fTabFolder = new TabFolder(parent, SWT.NONE);
		GridData gd = new GridData(GridData.FILL_BOTH);
		fTabFolder.setLayoutData(gd);
		fTabFolder.setFont(parent.getFont());
		if (size != null) {
			fTabFolder.setSize(size);
		}
		getTabFolder().addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				if (!isInitializingTabs()) {
					handleTabSelected();
				}
			}
		});		
	}
	
	/**
	 * Sets the apply button
	 */
	private void setApplyButton(Button button) {
		fApplyButton = button;
	}
	
	/**
	 * Returns the apply button
	 */
	protected Button getApplyButton() {
		return fApplyButton;
	}	
	
	/**
	 * Sets the revert button
	 */
	private void setRevertButton(Button button) {
		fRevertButton = button;
	}	
	
	/**
	 * Returns the revert button
	 */
	protected Button getRevertButton() {
		return fRevertButton;
	}	
	
	/**
	 * Sets the tab folder
	 */
	protected TabFolder getTabFolder() {
		return fTabFolder;
	}
		
	/**
	 * Returns the name widget
	 */
	private Text getNameWidget() {
		return fNameWidget;
	}
	
	/**
	 * Sets the name widget
	 */
	private void setNameWidget(Text nameText) {
		fNameWidget = nameText;
	}
	
	/**
	 * Sets the current name
	 */
	public void setName(String name) {
		if (getWorkingCopy() != null) {
			if (name == null) {
				name = ""; //$NON-NLS-1$
			}
			getNameWidget().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();
		} else {
			return new StructuredSelection(getActiveTab());
		}
	}

	/**
	 * @see org.eclipse.jface.viewers.Viewer#refresh()
	 */
	public void refresh() {
		if (isInitializingTabs()) {
			return;
		}
		
		ILaunchConfigurationTab[] tabs = getTabs();
		if (!isInitializingTabs() && tabs != null) {
			// update the working copy from the active tab
			getActiveTab().performApply(getWorkingCopy());
			updateButtons();
			// update error ticks
			TabFolder folder = getTabFolder();
			for (int i = 0; i < tabs.length; i++) {
				ILaunchConfigurationTab tab = tabs[i];
				tab.isValid(getWorkingCopy());
				boolean error = tab.getErrorMessage() != null;
				TabItem item = folder.getItem(i);
				setTabIcon(item, error, tab);
			}		
		}
	}

	private void updateButtons() {
		boolean dirty = isDirty();
		getApplyButton().setEnabled(dirty && canSave());
		getRevertButton().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(TabItem tabItem, boolean error, ILaunchConfigurationTab tab) {
		Image image = null;
		if (error) {
			image = DebugUIPlugin.getDefault().getLaunchConfigurationManager().getErrorTabImage(tab);
		} else {
			image = tab.getImage();
		}
		tabItem.setImage(image);
	}	

	/**
	 * @see org.eclipse.jface.viewers.Viewer#setInput(java.lang.Object)
	 */
	public void setInput(Object input) {
		if (input == null) {
			if (fInput == null) {
				return;
			} else {
				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;
						setOriginal(configuration);
						setWorkingCopy(configuration.getWorkingCopy());
						displayInstanceTabs();
					} else if (fInput instanceof ILaunchConfigurationType) {
						ILaunchConfiguration configuration = LaunchConfigurationManager.getSharedTypeConfig((ILaunchConfigurationType)fInput);
						setOriginal(configuration);
						setWorkingCopy(configuration.getWorkingCopy());
						displaySharedTabs();
					} else {
						setNoInput();
					}
					setRedraw(true);
				} catch (CoreException ce) {
					errorDialog(ce);
					setNoInput();
					setRedraw(true);
				}
			}
		};
		BusyIndicator.showWhile(getShell().getDisplay(), r);
	}
	
	private void setNoInput() {
		setOriginal(null);
		setWorkingCopy(null);
		getVisibleArea().setVisible(false);
		disposeExistingTabs();				
	}
	
	private void setRedraw(boolean b) {
		if (fRedraw != b) {
			fRedraw = b;
			getVisibleArea().setRedraw(fRedraw);
		}	
	}	
	/**
	 * Displays tabs for the current working copy
	 */
	protected void displayInstanceTabs() {
		// Turn on initializing flag to ignore message updates
		setInitializingTabs(true);

		ILaunchConfigurationType type = null;
		try {
			type = getWorkingCopy().getType();
			showInstanceTabsFor(type);
		} catch (CoreException e) {
			errorDialog(e);
			setInitializingTabs(false);
			return;
		}

		// show the name area
		fNameLabel.setVisible(true);
		fNameWidget.setVisible(true);
		// Update the name field before to avoid verify error
		getNameWidget().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.getString("LaunchConfigurationTabGroupViewer.No_tabs_defined_for_launch_configuration_type_{0}_1"), new String[]{type.getName()}), null); //$NON-NLS-1$
			CoreException e = new CoreException(status);
			errorDialog(e);
			setInitializingTabs(false);
			return;
		}

		// Update the tabs with the new working copy
		tabGroup.initializeFrom(getWorkingCopy());

		// Update the name field after in case client changed it
		getNameWidget().setText(getWorkingCopy().getName());
		
		fCurrentTabIndex = getTabFolder().getSelectionIndex();

		// Turn off initializing flag to update message
		setInitializingTabs(false);
		
		if (!getVisibleArea().isVisible()) {
			getVisibleArea().setVisible(true);
		}
		
		refreshStatus();		
	}
	
	/**
	 * Displays tabs for the current config type
	 */
	protected void displaySharedTabs() {
		// Turn on initializing flag to ignore message updates
		setInitializingTabs(true);

		ILaunchConfigurationType type = null;
		try {
			type = getWorkingCopy().getType();
			showSharedTabsFor(type);
		} catch (CoreException e) {
			errorDialog(e);
			setInitializingTabs(false);
			return;
		}

		// hide the name area
		fNameLabel.setVisible(false);
		fNameWidget.setVisible(false);
		// Update the name field before to avoid verify error
		getNameWidget().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.getString("LaunchConfigurationTabGroupViewer.No_tabs_defined_for_launch_configuration_type_{0}_1"), new String[]{type.getName()}), null); //$NON-NLS-1$
			CoreException e = new CoreException(status);
			errorDialog(e);
			setInitializingTabs(false);
			return;
		}

		// Update the tabs with the new working copy
		tabGroup.initializeFrom(getWorkingCopy());

		// Update the name field after in case client changed it
		getNameWidget().setText(getWorkingCopy().getName());
		
		fCurrentTabIndex = getTabFolder().getSelectionIndex();

		// Turn off initializing flag to update message
		setInitializingTabs(false);
		
		if (!getVisibleArea().isVisible()) {
			getVisibleArea().setVisible(true);
		}
		
		fDescription = getDescription(null);
		
		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 (getTabType() != null && getTabType().equals(configType) && !(getTabGroup() instanceof PerspectiveTabGroup)) {
			return;
		}

		// Build the new tabs
		ILaunchConfigurationTabGroup group = null;
		try {
			group = createGroup(configType);
		} catch (CoreException ce) {
			DebugUIPlugin.errorDialog(getShell(), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Error_19"), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Exception_occurred_creating_launch_configuration_tabs_27"),ce); //$NON-NLS-1$ //$NON-NLS-2$
			return;
		}

		showTabsFor(group);
		setTabGroup(group);
		setTabType(configType);
		
		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();
			LaunchConfigurationPresentationManager manager = LaunchConfigurationPresentationManager.getDefault();
			LaunchConfigurationTabGroupExtension extension = manager.getExtension(configType.getAttribute("id"), mode); //$NON-NLS-1$
			description = extension.getDescription(mode);
		}
	
		if (description == null)
			description = ""; //$NON-NLS-1$
		
		return description;
	}
	
	/**
	 * Populate the tabs in the configuration edit area for the shared info
	 * for the given launch config type.
	 */
	private void showSharedTabsFor(ILaunchConfigurationType configType) {

		// Don't do any work if the current tabs are for the current config type
		if (getTabType() != null && getTabType().equals(configType) && (getTabGroup() instanceof PerspectiveTabGroup)) {
			return;
		}		
		
		// Build the new tabs
		ILaunchConfigurationTabGroup group = new PerspectiveTabGroup(configType);
		group.createTabs(getLaunchConfigurationDialog(), getLaunchConfigurationDialog().getMode());
		ILaunchConfigurationTab[] tabs = group.getTabs();
		for (int i = 0; i < tabs.length; i++) {
			tabs[i].setLaunchConfigurationDialog(getLaunchConfigurationDialog());
		}
				
		showTabsFor(group);
		setTabType(configType);
		setTabGroup(group);		
	}		

	/**
	 * 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();

		setTabGroup(tabGroup);

		// Create the Control for each tab
		ILaunchConfigurationTab[] tabs = tabGroup.getTabs();
		for (int i = 0; i < tabs.length; i++) {
			TabItem tab = new TabItem(getTabFolder(), SWT.NONE);
			String name = tabs[i].getName();
			if (name == null) {
				name = LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.unspecified_28"); //$NON-NLS-1$
			}
			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;
							getTabFolder().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() {
		TabFolder folder = getTabFolder();
		ILaunchConfigurationTab[] tabs = getTabs();
		if (folder != null && tabs != null) {
			int pageIndex = folder.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 (!isInitializingTabs()) {
			getLaunchConfigurationDialog().updateButtons();
			getLaunchConfigurationDialog().updateMessage();
		}
	}	
	
	/**
	 * Returns the containing launch dialog
	 */
	protected ILaunchConfigurationDialog getLaunchConfigurationDialog() {
		return fDialog;
	}
	
	/**
	 * Sets the launch configuration being displayed/edited, possilby
	 * <code>null</code>.
	 */
	private void setOriginal(ILaunchConfiguration configuration) {
		fOriginal = configuration;
	}
	
	/**
	 * Returns the original launch configuration being edited, possibly
	 * <code>null</code>.
	 * 
	 * @return ILaunchConfiguration
	 */
	protected ILaunchConfiguration getOriginal() {
		return fOriginal;
	}
	
	/**
	 * Sets the working copy used to edit the original.
	 */
	private void setWorkingCopy(ILaunchConfigurationWorkingCopy workingCopy) {
		fWorkingCopy = workingCopy;
	}
	
	/**
	 * 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 (isInitializingTabs()) {
			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(isInitializingTabs()) {
			return false;
		}
		
		if (getActiveTab() instanceof PerspectivesTab) {
			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 (isInitializingTabs()) {
			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;
		} else {
			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(removeAmpersandsFrom(tab.getName()));
				temp.append("]: "); //$NON-NLS-1$
				temp.append(message);
				return temp.toString();
			}
		}
		return null;
	}
	
	/**
	 * Return a copy of the specified string without ampersands.
	 */
	private String removeAmpersandsFrom(String string) {
		String newString = new String(string);
		int index = newString.indexOf('&');
		while (index != -1) {
			newString = string.substring(0, index) + newString.substring(index + 1, newString.length());
			index = newString.indexOf('&');
		}
		return newString;
	}	
	
	/**
	 * 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 (isInitializingTabs()) {
			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 = getNameWidget().getText().trim();
	
			// If there is no name, complain
			if (currentName.length() < 1) {
				throw new CoreException(new Status(IStatus.ERROR,
													 DebugUIPlugin.getUniqueIdentifier(),
													 0,
													 LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Name_required_for_launch_configuration_11"), //$NON-NLS-1$
													 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));
			}
	
			// Otherwise, if there's already a config with the same name, complain
			if (!getOriginal().getName().equals(currentName)) {
				if (getLaunchManager().isExistingLaunchConfigurationName(currentName)) {
					throw new CoreException(new Status(IStatus.ERROR,
														 DebugUIPlugin.getUniqueIdentifier(),
														 0,
														 LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Launch_configuration_already_exists_with_this_name_12"), //$NON-NLS-1$
														 null));
				}
			}
		}
	}
	
	private void setDisposingTabs(boolean disposing) {
		fDisposingTabs = disposing;
	}

	private boolean isDisposingTabs() {
		return fDisposingTabs;
	}
	
	private void setInitializingTabs(boolean initializing) {
		fInitializingTabs = initializing;
	}

	private boolean isInitializingTabs() {
		return fInitializingTabs;
	}		
	
	private void disposeExistingTabs() {
		setDisposingTabs(true);
		TabItem[] oldTabs = getTabFolder().getItems();
		for (int i = 0; i < oldTabs.length; i++) {
			oldTabs[i].dispose();
		}
		createTabFolder(fTabComposite);
		disposeTabGroup();
		setDisposingTabs(false);
	}	
	
	private ILaunchManager getLaunchManager() {
		return DebugPlugin.getDefault().getLaunchManager();
	}
	
	/**
	 * Returns the type that tabs are currently displayed
	 * for, or <code>null</code> if none.
	 *
	 * @return launch configuration type or <code>null</code>
	 */
	private ILaunchConfigurationType getTabType() {
		return fTabType;
	}

	/**
	 * Sets the type that tabs are currently displayed
	 * for, or <code>null</code> if none.
	 *
	 * @param tabType launch configuration type
	 */
	private void setTabType(ILaunchConfigurationType tabType) {
		fTabType = tabType;
	}	
	
	/**
	 * Sets the current tab group being displayed
	 *
	 * @param group the current tab group being displayed
	 */
	private void setTabGroup(ILaunchConfigurationTabGroup group) {
		fTabGroup = group;
	}

	/**
	 * 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 (isDisposingTabs()) {
			return;
		}
		ILaunchConfigurationTab[] tabs = getTabs();
		if (fCurrentTabIndex == getTabFolder().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 = getTabFolder().getSelectionIndex();
		SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection());
		fireSelectionChanged(event);
	}
	
	/**
	 * Notification the name field has been modified
	 */
	protected void handleNameModified() {
		getWorkingCopy().rename(getNameWidget().getText().trim());
		refreshStatus();
	}		
	
	/**
	 * Notification that the 'Apply' button has been pressed
	 */
	protected void handleApplyPressed() {
		try {
			// trim name
			Text widget = getNameWidget();
			String name = widget.getText();
			String trimmed = name.trim();

			// update launch config
			setInitializingTabs(true);
			if (!name.equals(trimmed)) {
				widget.setText(trimmed);
			}
			getWorkingCopy().rename(trimmed);
			getTabGroup().performApply(getWorkingCopy());
			setInitializingTabs(false);
			//
			
			if (isDirty()) {
				getWorkingCopy().doSave();
			}
			updateButtons();
		} catch (CoreException e) {
			DebugUIPlugin.errorDialog(getShell(), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Launch_Configuration_Error_46"), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Exception_occurred_while_saving_launch_configuration_47"), e); //$NON-NLS-1$ //$NON-NLS-2$
			return;
		}
	}

	/**
	 * Notification that the 'Revert' button has been pressed
	 */
	protected void handleRevertPressed() {
		if (getActiveTab() instanceof PerspectivesTab) {
			inputChanged(getTabType());	
		} else {
			inputChanged(getOriginal());
		}
	}	
	
	/**
	 * Show an error dialog on the given exception.
	 *
	 * @param exception
	 */
	protected void errorDialog(CoreException exception) {
		ErrorDialog.openError(getShell(), null, null, exception.getStatus());
	}	
	
	protected void setVisibleArea(Composite control) {
		fVisibleArea = control;
	}
	
	protected Composite getVisibleArea() {
		return fVisibleArea;
	}
	
	/**
	 * 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) {
			getTabFolder().setSelection(index);
			handleTabSelected();
		}
	}
}

Back to the top