org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsDialog.java

Source

/*******************************************************************************
 *  Copyright (c) 2000, 2011 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
 *     Sebastian Davids - Bug 137923
 *******************************************************************************/
package org.eclipse.debug.internal.ui.launchConfigurations;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
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.core.IStatusHandler;
import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
import org.eclipse.debug.internal.core.LaunchConfigurationWorkingCopy;
import org.eclipse.debug.internal.core.LaunchManager;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.IDebugHelpContextIds;
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.IDebugView;
import org.eclipse.debug.ui.ILaunchConfigurationDialog;
import org.eclipse.debug.ui.ILaunchConfigurationTab;
import org.eclipse.debug.ui.ILaunchConfigurationTabGroup;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.operation.ModalContext;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
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.StructuredViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.wizard.ProgressMonitorPart;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ViewForm;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.WorkbenchJob;

import com.ibm.icu.text.MessageFormat;

/**
 * The dialog used to edit and launch launch configurations.
 */
public class LaunchConfigurationsDialog extends TitleAreaDialog
        implements ILaunchConfigurationDialog, IPropertyChangeListener {

    /**
     * Keep track of the currently visible dialog instance
     */
    private static ILaunchConfigurationDialog fgCurrentlyVisibleLaunchConfigurationDialog;
    /**
     * Id for 'Launch' button.
     */
    protected static final int ID_LAUNCH_BUTTON = IDialogConstants.CLIENT_ID + 1;

    /**
     * Id for 'Close' button.
     */
    protected static final int ID_CLOSE_BUTTON = IDialogConstants.CLIENT_ID + 2;
    /**
     * Id for 'Cancel' button.
     */
    protected static final int ID_CANCEL_BUTTON = IDialogConstants.CLIENT_ID + 3;

    /**
     * The id for the 'No' button on the discard changes message box
     * @since 3.3
     */
    protected static final int ID_DISCARD_BUTTON = IDialogConstants.CLIENT_ID + 4;

    /**
     * Constant specifying how wide this dialog is allowed to get (as a percentage of
     * total available screen width) as a result of tab labels in the edit area.
     */
    protected static final float MAX_DIALOG_WIDTH_PERCENT = 0.75f;
    /**
     * Constant specifying how tall this dialog is allowed to get (as a percentage of
     * total available screen height) as a result of preferred tab size.
     */
    protected static final float MAX_DIALOG_HEIGHT_PERCENT = 0.65f;
    /**
     * Size of this dialog if there is no preference specifying a size.
     */
    protected static final Point DEFAULT_INITIAL_DIALOG_SIZE = new Point(800, 640);
    /**
     * defines some default sash weights when we have a new workspace
     * @since 3.2
     */
    private static final int[] DEFAULT_SASH_WEIGHTS = new int[] { 190, 610 };
    /**
     * Constant specifying that this dialog should be opened with the last configuration launched
     * in the workspace selected.
     */
    public static final int LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_LAST_LAUNCHED = 2;
    /**
     * Constant specifying that this dialog should be opened with the value specified via
     * <code>setInitialSelection()</code> selected.
     */
    public static final int LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_SELECTION = 3;
    /**
     * Constant specifying that a new launch configuration dialog was not opened.  Instead
     * an existing launch configuration dialog was used.
     */
    public static final int LAUNCH_CONFIGURATION_DIALOG_REUSE_OPEN = 4;
    /**
     * defines the delimiter used in the persistence of the expanded state
     * @since 3.2
     */
    private static final String DELIMITER = ", "; //$NON-NLS-1$
    /**
     * Specifies how this dialog behaves when opened.  Value is one of the
     * 'LAUNCH_CONFIGURATION_DIALOG' constants defined in this class.
     */
    private int fOpenMode = LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_LAST_LAUNCHED;

    /**
     * dialog settings
     */
    private static final String DIALOG_SASH_WEIGHTS_1 = IDebugUIConstants.PLUGIN_ID + ".DIALOG_SASH_WEIGHTS_1"; //$NON-NLS-1$
    private static final String DIALOG_SASH_WEIGHTS_2 = IDebugUIConstants.PLUGIN_ID + ".DIALOG_SASH_WEIGHTS_2"; //$NON-NLS-1$
    private static final String DIALOG_EXPANDED_NODES = IDebugUIConstants.PLUGIN_ID + ".EXPANDED_NODES"; //$NON-NLS-1$

    /**
     * Returns the currently visible dialog
     * @return the currently visible launch dialog
     */
    public static ILaunchConfigurationDialog getCurrentlyVisibleLaunchConfigurationDialog() {
        return fgCurrentlyVisibleLaunchConfigurationDialog;
    }

    /**
     * Sets which launch dialog is currently the visible one
     * @param dialog the dialog to set as the visible one
     */
    public static void setCurrentlyVisibleLaunchConfigurationDialog(ILaunchConfigurationDialog dialog) {
        fgCurrentlyVisibleLaunchConfigurationDialog = dialog;
    }

    /**
     * widgets
     */
    private Control fLastControl;
    private Composite fButtonComp;
    private SashForm fSashForm;
    private LaunchConfigurationView fLaunchConfigurationView;
    private LaunchConfigurationTabGroupViewer fTabViewer;
    private ProgressMonitorPart fProgressMonitorPart;
    private LaunchGroupExtension fGroup;
    private Image fBannerImage;

    /**
     * When this dialog is opened in <code>LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_SELECTION</code>
     * mode, this specifies the selection that is initially shown in the dialog.
     */
    private IStructuredSelection fInitialSelection;

    /**
     * The status to open the dialog on, or <code>null</code> if none.
     */
    private IStatus fInitialStatus;

    /**
     * The number of 'long-running' operations currently taking place in this dialog
     */
    private long fActiveRunningOperations = 0;

    /**
     * Double-click action
     */
    private IAction fDoubleClickAction;

    /**
     * Filters for the LCD
     * @since 3.2
     */
    private ClosedProjectFilter fClosedProjectFilter;
    private DeletedProjectFilter fDeletedProjectFilter;
    private LaunchConfigurationTypeFilter fLCTFilter;
    private WorkingSetsFilter fWorkingSetsFilter;

    /**
     * set of reserved names that should not be considered when generating a new name for a launch configuration
     */
    protected Set fReservedNames = null;

    /**
     * Whether to set default values when opened
     * @since 3.6
     */
    private boolean fSetDefaultOnOpen = false;

    /**
     * Whether in the process of setting the input to the tab viewer
     */
    private boolean fSettingInput = false;

    /**
     * Constructs a new launch configuration dialog on the given
     * parent shell.
     * 
     * @param shell the parent shell
     * @param group the group of launch configuration to display
     */
    public LaunchConfigurationsDialog(Shell shell, LaunchGroupExtension group) {
        super(shell);
        setShellStyle(getShellStyle() | SWT.RESIZE);
        setLaunchGroup(group);
    }

    /**
     * Adds content to the dialog area
     * 
     * @param dialogComp
     */
    protected void addContent(Composite dialogComp) {
        GridData gd;
        Composite topComp = new Composite(dialogComp, SWT.NONE);
        gd = new GridData(GridData.FILL_BOTH);
        topComp.setLayoutData(gd);
        GridLayout topLayout = new GridLayout(2, false);
        topLayout.marginHeight = 5;
        topLayout.marginWidth = 5;
        topComp.setLayout(topLayout);

        // Set the things that TitleAreaDialog takes care of
        setTitle(
                LaunchConfigurationsMessages.LaunchConfigurationDialog_Create__manage__and_run_launch_configurations_8);
        setMessage(LaunchConfigurationsMessages.LaunchConfigurationDialog_Ready_to_launch_2);
        setModeLabelState();

        // Create the SashForm that contains the selection area on the left,
        // and the edit area on the right
        gd = new GridData(GridData.FILL_BOTH);
        gd.horizontalSpan = 2;
        SashForm sash = new SashForm(topComp, SWT.SMOOTH);
        sash.setOrientation(SWT.HORIZONTAL);
        sash.setLayoutData(gd);
        sash.setFont(dialogComp.getFont());
        sash.setVisible(true);
        fSashForm = sash;

        // Build the launch configuration selection area and put it into the composite.
        Control launchConfigSelectionArea = createLaunchConfigurationSelectionArea(fSashForm);
        gd = new GridData(GridData.FILL_VERTICAL);
        launchConfigSelectionArea.setLayoutData(gd);

        // Build the launch configuration edit area and put it into the composite.
        Composite editAreaComp = createLaunchConfigurationEditArea(fSashForm);
        gd = new GridData(GridData.FILL_BOTH);
        editAreaComp.setLayoutData(gd);

        dialogComp.layout(true);
        applyDialogFont(dialogComp);
    }

    /**
     * Handle the 'close' & 'launch' buttons here, all others are handled
     * in <code>Dialog</code>
     * 
     * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int)
     */
    protected void buttonPressed(int buttonId) {
        if (buttonId == ID_LAUNCH_BUTTON) {
            handleLaunchPressed();
        } else if (buttonId == ID_CLOSE_BUTTON) {
            handleClosePressed();
        } else {
            super.buttonPressed(buttonId);
        }
    }

    /**
     * Return whether the current configuration should be saved or discarded.  This involves determining
     * if it is dirty, and if it is, asking the user what to do.
     * 
     * @return if we can discard the current config or not
     */
    protected int shouldSaveCurrentConfig() {
        if (fTabViewer.isDirty()) {
            if (fTabViewer.canSave()) {
                return showSaveChangesDialog();
            }
            return showUnsavedChangesDialog();
        }
        return IDialogConstants.NO_ID;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.window.Window#close()
     */
    public boolean close() {
        if (!isSafeToClose()) {
            return false;
        }
        persistSashWeights();
        persistExpansion();
        setCurrentlyVisibleLaunchConfigurationDialog(null);
        fTabViewer.dispose();
        if (fLaunchConfigurationView != null) {
            fLaunchConfigurationView.dispose();
        }
        DebugUIPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this);
        boolean result = super.close();
        getBannerImage().dispose();
        return result;
    }

    /**
     * Sets the title for the dialog, and establishes the help context.
     * 
     * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell);
     */
    protected void configureShell(Shell shell) {
        super.configureShell(shell);
        shell.setText(getShellTitle());
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.window.Window#create()
     */
    public void create() {
        super.create();
        if (fTabViewer.getInput() == null) {
            fTabViewer.inputChanged(null);
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#createButtonBar(org.eclipse.swt.widgets.Composite)
     */
    protected Control createButtonBar(Composite parent) {
        Font font = parent.getFont();
        Composite composite = new Composite(parent, SWT.NULL);
        GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        layout.marginLeft = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        composite.setFont(font);
        // create help control if needed
        if (isHelpAvailable()) {
            createHelpControl(composite);
        }
        Composite monitorComposite = new Composite(composite, SWT.NULL);
        layout = new GridLayout();
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        layout.numColumns = 2;
        monitorComposite.setLayout(layout);
        monitorComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        GridLayout pmLayout = new GridLayout();
        fProgressMonitorPart = new ProgressMonitorPart(monitorComposite, pmLayout, true);
        fProgressMonitorPart.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        fProgressMonitorPart.setFont(font);
        monitorComposite.setVisible(false);

        /*
         * Create the rest of the button bar, but tell it not to
         * create a help button (we've already created it).
         */
        boolean helpAvailable = isHelpAvailable();
        setHelpAvailable(false);
        fButtonComp = (Composite) super.createButtonBar(composite);
        setHelpAvailable(helpAvailable);
        return composite;
    }

    /**
     * A launch configuration dialog overrides this method
     * to create a custom set of buttons in the button bar.
     * This dialog has 'Launch' and 'Cancel'
     * buttons.
     * 
     * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite)
     */
    protected void createButtonsForButtonBar(Composite parent) {
        Button button = createButton(parent, ID_LAUNCH_BUTTON, getLaunchButtonText(), true);
        button.setEnabled(false);
        createButton(parent, ID_CLOSE_BUTTON, LaunchConfigurationsMessages.LaunchConfigurationDialog_Close_1,
                false);
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.window.Window#createContents(org.eclipse.swt.widgets.Composite)
     */
    protected Control createContents(Composite parent) {
        Control contents = super.createContents(parent);
        initializeContent();
        PlatformUI.getWorkbench().getHelpSystem().setHelp(getShell(), getHelpContextId());
        return contents;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
     */
    protected Control createDialogArea(Composite parent) {
        Composite dialogComp = (Composite) super.createDialogArea(parent);
        addContent(dialogComp);
        if (fLaunchConfigurationView != null) {
            fLaunchConfigurationView.updateFilterLabel();
        }
        return dialogComp;
    }

    /**
     * Creates the launch configuration edit area of the dialog.
     * 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
     */
    protected Composite createLaunchConfigurationEditArea(Composite parent) {
        setTabViewer(new LaunchConfigurationTabGroupViewer(parent, this));
        return (Composite) fTabViewer.getControl();
    }

    /**
     * Creates all of the actions for the toolbar
     * @param toolbar
     * @since 3.2
     */
    protected void createToolbarActions(ToolBarManager tmanager) {
        tmanager.add(getNewAction());
        tmanager.add(getDuplicateAction());
        tmanager.add(getDeleteAction());
        tmanager.add(new Separator());
        tmanager.add(getCollapseAllAction());
        tmanager.add(getFilterAction());
        tmanager.update(true);
        DebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this);
    }

    /**
     * Creates the launch configuration selection area of the dialog.
     * This area displays a tree of launch configurations that the user
     * may select, and allows users to create new configurations, and
     * delete and duplicate existing configurations.
     * 
     * @return the composite used for launch configuration selection area
     */
    protected Control createLaunchConfigurationSelectionArea(Composite parent) {
        Composite comp = new Composite(parent, SWT.FLAT);
        GridLayout gridLayout = new GridLayout(1, false);
        gridLayout.marginHeight = 0;
        gridLayout.marginWidth = 0;
        comp.setLayout(gridLayout);
        comp.setLayoutData(new GridData(GridData.FILL_BOTH));

        ViewForm viewForm = new ViewForm(comp, SWT.FLAT | SWT.BORDER);
        ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
        ToolBar toolBar = toolBarManager.createControl(viewForm);
        toolBar.setBackground(parent.getBackground());
        viewForm.setTopLeft(toolBar);
        viewForm.setLayoutData(new GridData(GridData.FILL_BOTH));

        Composite viewFormContents = new Composite(viewForm, SWT.FLAT);
        gridLayout = new GridLayout();
        gridLayout.marginHeight = 5;
        gridLayout.marginWidth = 5;
        viewFormContents.setLayout(gridLayout);
        viewFormContents.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
        fLaunchConfigurationView = new LaunchConfigurationView(getLaunchGroup(), createViewerFilters());
        fLaunchConfigurationView.createLaunchDialogControl(viewFormContents);
        Text filterText = fLaunchConfigurationView.getFilteringTextControl();
        if (filterText != null) {
            filterText.setFocus();
        }

        //create toolbar actions, we reuse the actions from the view so we wait until after
        //the view is created to add them to the toolbar
        createToolbarActions(toolBarManager);
        fDoubleClickAction = new Action() {
            public void run() {
                IStructuredSelection selection = (IStructuredSelection) fLaunchConfigurationView.getViewer()
                        .getSelection();
                Object target = selection.getFirstElement();
                if (target instanceof ILaunchConfiguration) {
                    if (fTabViewer.canLaunch() & fTabViewer.canLaunchWithModes()
                            & !fTabViewer.hasDuplicateDelegates()) {
                        handleLaunchPressed();
                    }
                } else {
                    getNewAction().run();
                }
            }
        };
        fLaunchConfigurationView.setAction(IDebugView.DOUBLE_CLICK_ACTION, fDoubleClickAction);
        Viewer viewer = fLaunchConfigurationView.getViewer();

        Control control = viewer.getControl();
        GridData gd = new GridData(GridData.FILL_BOTH);
        control.setLayoutData(gd);
        viewForm.setContent(viewFormContents);
        AbstractLaunchConfigurationAction.IConfirmationRequestor requestor = new AbstractLaunchConfigurationAction.IConfirmationRequestor() {
            public boolean getConfirmation() {
                int status = shouldSaveCurrentConfig();
                if (status == IDialogConstants.YES_ID) {
                    fTabViewer.handleApplyPressed();
                    return true;
                } else if (status == IDialogConstants.NO_ID) {
                    fTabViewer.handleRevertPressed();
                    return true;
                }
                return false;
            }
        };
        getDuplicateAction().setConfirmationRequestor(requestor);
        getNewAction().setConfirmationRequestor(requestor);
        ((StructuredViewer) viewer).addPostSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                handleLaunchConfigurationSelectionChanged(event);
                getNewAction().setEnabled(getNewAction().isEnabled());
                getDeleteAction().setEnabled(getDeleteAction().isEnabled());
                getDuplicateAction().setEnabled(getDuplicateAction().isEnabled());
            }
        });
        return comp;
    }

    /**
     * Create the filters to be initially applied to the viewer.
     * The initial filters are based on the persisted preferences
     * @return the array of initial filters
     * @since 3.2
     */
    private ViewerFilter[] createViewerFilters() {
        ArrayList filters = new ArrayList();
        fClosedProjectFilter = new ClosedProjectFilter();
        if (DebugUIPlugin.getDefault().getPreferenceStore()
                .getBoolean(IInternalDebugUIConstants.PREF_FILTER_LAUNCH_CLOSED)) {
            filters.add(fClosedProjectFilter);
        }
        fDeletedProjectFilter = new DeletedProjectFilter();
        if (DebugUIPlugin.getDefault().getPreferenceStore()
                .getBoolean(IInternalDebugUIConstants.PREF_FILTER_LAUNCH_DELETED)) {
            filters.add(fDeletedProjectFilter);
        }
        fLCTFilter = new LaunchConfigurationTypeFilter();
        if (DebugUIPlugin.getDefault().getPreferenceStore()
                .getBoolean(IInternalDebugUIConstants.PREF_FILTER_LAUNCH_TYPES)) {
            filters.add(fLCTFilter);
        }
        fWorkingSetsFilter = new WorkingSetsFilter();
        if (DebugUIPlugin.getDefault().getPreferenceStore()
                .getBoolean(IInternalDebugUIConstants.PREF_FILTER_WORKING_SETS)) {
            filters.add(fWorkingSetsFilter);
        }
        return (ViewerFilter[]) filters.toArray(new ViewerFilter[filters.size()]);
    }

    /**
     * Set the initial selection in the tree.
     */
    public void doInitialTreeSelection() {
        fLaunchConfigurationView.getViewer().setSelection(fInitialSelection);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationDialog#generateName(java.lang.String)
     */
    public String generateName(String name) {
        if (name == null) {
            name = IInternalDebugCoreConstants.EMPTY_STRING;
        }
        return getLaunchManager().generateLaunchConfigurationName(name);
    }

    /**
     * Generates and returns a unique name using the specified name as a prefix in the event
     * the specified name already exists or is contained in the set of reserved names.
     * @param name the name to use as a prefix for generating a new name
     * @param reservednames a listing of names that should be considered as 'taken' and cannot be generated
     * by this method
     * @return a new name based on the specified name.
     * 
     * @since 3.3
     */
    public String generateName(String name, Set reservednames) {
        if (name == null) {
            name = IInternalDebugCoreConstants.EMPTY_STRING;
        }
        return ((LaunchManager) getLaunchManager()).generateUniqueLaunchConfigurationNameFrom(name, reservednames);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationDialog#getActiveTab()
     */
    public ILaunchConfigurationTab getActiveTab() {
        return fTabViewer.getActiveTab();
    }

    /**
     * Returns the banner image to display in the title area
     */
    protected Image getBannerImage() {
        if (fBannerImage == null) {
            ImageDescriptor descriptor = getLaunchGroup().getBannerImageDescriptor();
            if (descriptor != null) {
                fBannerImage = descriptor.createImage();
            }
        }
        return fBannerImage;
    }

    /**
     * Gets the delete menu action
     * 
     * @return the delete menu action
     */
    protected AbstractLaunchConfigurationAction getDeleteAction() {
        return (AbstractLaunchConfigurationAction) fLaunchConfigurationView
                .getAction(DeleteLaunchConfigurationAction.ID_DELETE_ACTION);
    }

    /**
     * Gets the filter action
     * @return the filter menu action
     * @since 3.2
     */
    protected IAction getFilterAction() {
        return fLaunchConfigurationView.getAction(FilterLaunchConfigurationAction.ID_FILTER_ACTION);
    }

    /**
     * Gets the collapse all action
     * @return the collapse all action
     * @since 3.2
     */
    protected IAction getCollapseAllAction() {
        return fLaunchConfigurationView.getAction(CollapseAllLaunchConfigurationAction.ID_COLLAPSEALL_ACTION);
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsSettings()
     * @since 3.2
     */
    protected IDialogSettings getDialogBoundsSettings() {
        return getDialogSettings();
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsStrategy()
     */
    protected int getDialogBoundsStrategy() {
        return DIALOG_PERSISTSIZE;
    }

    /**
     * Returns the dialog settings for this dialog. Subclasses should override
     * <code>getDialogSettingsSectionName()</code>.
     * 
     * @return IDialogSettings
     */
    protected IDialogSettings getDialogSettings() {
        IDialogSettings settings = DebugUIPlugin.getDefault().getDialogSettings();
        IDialogSettings section = settings.getSection(getDialogSettingsSectionName());
        if (section == null) {
            section = settings.addNewSection(getDialogSettingsSectionName());
        }
        return section;
    }

    /**
     * Returns the name of the section that this dialog stores its settings in
     * 
     * @return String
     */
    protected String getDialogSettingsSectionName() {
        return IDebugUIConstants.PLUGIN_ID + ".LAUNCH_CONFIGURATIONS_DIALOG_SECTION"; //$NON-NLS-1$
    }

    /**
     * Gets the current display
     * 
     * @return the display
     */
    protected Display getDisplay() {
        Shell shell = getShell();
        if (shell != null) {
            return shell.getDisplay();
        }
        return DebugUIPlugin.getStandardDisplay();
    }

    /**
     * Gets the duplicate menu action
     * 
     * @return the duplicate menu action
     */
    protected AbstractLaunchConfigurationAction getDuplicateAction() {
        return (AbstractLaunchConfigurationAction) fLaunchConfigurationView
                .getAction(DuplicateLaunchConfigurationAction.ID_DUPLICATE_ACTION);
    }

    /**
     * Gets the help context id
     * 
     * @return the help context id
     */
    protected String getHelpContextId() {
        return IDebugHelpContextIds.LAUNCH_CONFIGURATION_DIALOG;
    }

    /**
    * Returns the status the dialog was opened on or <code>null</code> if none.
    * 
    * @return IStatus
    */
    protected IStatus getInitialStatus() {
        return fInitialStatus;
    }

    /**
    * Return the last launched configuration in the workspace.
    * 
    * @return the last launched configuration
    */
    protected ILaunchConfiguration getLastLaunchedWorkbenchConfiguration() {
        return DebugUIPlugin.getDefault().getLaunchConfigurationManager()
                .getLastLaunch(getLaunchGroup().getIdentifier());
    }

    /**
    * Returns the appropriate text for the launch button - run or debug.
    * 
    * @return the launch button text
    */
    protected String getLaunchButtonText() {
        return DebugPlugin.getDefault().getLaunchManager().getLaunchMode(getMode()).getLabel();
    }

    /**
    * Returns the launch group being displayed.
    * 
    * @return launch group
    */
    public LaunchGroupExtension getLaunchGroup() {
        return fGroup;
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationDialog#getMode()
     */
    public String getMode() {
        return getLaunchGroup().getMode();
    }

    /**
     * Gets the new menu action
     * 
     * @return the new menu action
     */
    protected AbstractLaunchConfigurationAction getNewAction() {
        return (AbstractLaunchConfigurationAction) fLaunchConfigurationView
                .getAction(CreateLaunchConfigurationAction.ID_CREATE_ACTION);
    }

    /**
     * Returns the reserved name set (if there is one), <code>null</code> otherwise
     * @return the reserved name set or <code>null</code>
     * @since 3.3
     * 
     */
    public Set getReservedNameSet() {
        return fReservedNames;
    }

    /**
     * returns the open mode
     * 
     * @return the open mode
     */
    protected int getOpenMode() {
        return fOpenMode;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.IPageChangeProvider#getSelectedPage()
     */
    public Object getSelectedPage() {
        return getActiveTab();
    }

    /**
     * Returns the title of the shell
     * @return the shell title
     */
    protected String getShellTitle() {
        String title = null;
        if (getLaunchGroup() != null) {
            title = MessageFormat.format(LaunchConfigurationsMessages.LaunchConfigurationsDialog_configurations,
                    new String[] { DebugUIPlugin.removeAccelerators(getLaunchGroup().getLabel()) });
        }
        if (title == null) {
            title = LaunchConfigurationsMessages.LaunchConfigurationDialog_Launch_Configurations_18;
        }
        return title;
    }

    /**
      * Returns the current tab group
      * 
      * @return the current tab group, or <code>null</code> if none
      */
    public ILaunchConfigurationTabGroup getTabGroup() {
        if (fTabViewer != null) {
            return fTabViewer.getTabGroup();
        }
        return null;
    }

    /* (non-Javadoc)
      * @see org.eclipse.debug.ui.ILaunchConfigurationDialog#getTabs()
      */
    public ILaunchConfigurationTab[] getTabs() {
        if (getTabGroup() == null) {
            return null;
        }
        return getTabGroup().getTabs();
    }

    /**
     * Returns the viewer used to display the tabs for a launch configuration.
     * 
     * @return LaunchConfigurationTabGroupViewer
     */
    protected LaunchConfigurationTabGroupViewer getTabViewer() {
        return fTabViewer;
    }

    /**
     * Notification the 'Close' button has been pressed.
     */
    protected void handleClosePressed() {
        if (fTabViewer.canSave()) {
            int status = shouldSaveCurrentConfig();
            if (status != IDialogConstants.CANCEL_ID) {
                if (status != ID_DISCARD_BUTTON) {
                    if (status == IDialogConstants.YES_ID) {
                        fTabViewer.handleApplyPressed();
                    }
                    cancelPressed();
                }
            }
        } else {
            cancelPressed();
        }
    }

    /**
     * Notification that selection has changed in the launch configuration tree.
     * <p>
     * If the currently displayed configuration is not saved,
     * prompt for saving before moving on to the new selection.
     * </p>
     * 
     * @param event selection changed event
     */
    protected void handleLaunchConfigurationSelectionChanged(SelectionChangedEvent event) {
        Object input = fTabViewer.getInput();
        Object newInput = null;
        IStructuredSelection selection = (IStructuredSelection) event.getSelection();
        if (selection.size() == 1) {
            newInput = selection.getFirstElement();
        }
        if (!isEqual(input, newInput)) {
            ILaunchConfiguration original = fTabViewer.getOriginal();
            if (original != null && newInput == null && getLaunchManager().getMovedTo(original) != null) {
                return;
            }
            boolean deleted = false;
            if (original != null) {
                deleted = !original.exists();
            }
            boolean renamed = false;
            if (newInput instanceof ILaunchConfiguration) {
                renamed = getLaunchManager().getMovedFrom((ILaunchConfiguration) newInput) != null;
            }
            try {
                fSettingInput = true;
                if (fTabViewer.canSave() && fTabViewer.isDirty() && !deleted && !renamed) {
                    if (fLaunchConfigurationView != null) {
                        fLaunchConfigurationView.setAutoSelect(false);
                    }
                    int ret = showUnsavedChangesDialog();
                    if (ret == IDialogConstants.YES_ID) {
                        fTabViewer.handleApplyPressed();
                        fTabViewer.setInput(newInput);
                    } else if (ret == IDialogConstants.NO_ID) {
                        fTabViewer.handleRevertPressed();
                        fTabViewer.setInput(newInput);
                    } else {
                        fLaunchConfigurationView.getViewer().setSelection(new StructuredSelection(input));
                    }
                    fLaunchConfigurationView.setAutoSelect(true);
                } else {
                    fTabViewer.setInput(newInput);
                    if (fTabViewer.isDirty()) {
                        fTabViewer.handleApplyPressed();
                    }
                }
            } finally {
                fSettingInput = false;
                updateButtons();
                updateMessage();
            }
            if (getShell() != null && getShell().isVisible()) {
                resize();
            }
        }
    }

    /**
     * Notification the 'launch' button has been pressed.
     * Save and launch.
     */
    protected void handleLaunchPressed() {
        ILaunchConfiguration config = fTabViewer.getOriginal();
        if (fTabViewer.isDirty() && fTabViewer.canSave()) {
            config = fTabViewer.handleApplyPressed();
        }
        if (config != null) {
            close();
            DebugUITools.launch(config, getMode());
        }
    }

    /**
     * Consult a status handler for the given status, if any. The status handler
     * is passed this launch config dialog as an argument.
     * 
     * @param status the status to be handled
     */
    public void handleStatus(IStatus status) {
        IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(status);
        if (handler != null) {
            try {
                handler.handleStatus(status, this);
                return;
            } catch (CoreException e) {
                status = e.getStatus();
            }
        }
        // if no handler, or handler failed, display error/warning dialog
        String title = null;
        switch (status.getSeverity()) {
        case IStatus.ERROR:
            title = LaunchConfigurationsMessages.LaunchConfigurationsDialog_Error_1;
            break;
        case IStatus.WARNING:
            title = LaunchConfigurationsMessages.LaunchConfigurationsDialog_Warning_2;
            break;
        default:
            title = LaunchConfigurationsMessages.LaunchConfigurationsDialog_Information_3;
            break;
        }
        ErrorDialog.openError(getShell(), title, null, status);
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.window.Window#initializeBounds()
     */
    protected void initializeBounds() {
        IDialogSettings settings = getDialogSettings();
        if (fSashForm != null) {
            int w1, w2;
            try {
                w1 = settings.getInt(DIALOG_SASH_WEIGHTS_1);
                if (w1 < 10) {
                    w1 = DEFAULT_SASH_WEIGHTS[0];
                }
                w2 = settings.getInt(DIALOG_SASH_WEIGHTS_2);
                if (w2 < 10) {
                    w2 = DEFAULT_SASH_WEIGHTS[1];
                }
            } catch (NumberFormatException nfe) {
                w1 = DEFAULT_SASH_WEIGHTS[0];
                w2 = DEFAULT_SASH_WEIGHTS[1];
            }
            fSashForm.setWeights(new int[] { w1, w2 });
        }
        super.initializeBounds();
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.TitleAreaDialog#getInitialSize()
     */
    protected Point getInitialSize() {
        try {
            getDialogSettings().getInt("DIALOG_HEIGHT"); //$NON-NLS-1$
            return super.getInitialSize();
        } catch (NumberFormatException nfe) {
            return DEFAULT_INITIAL_DIALOG_SIZE;
        }
    }

    /**
     * Sets the default values for the given {@link LaunchConfigurationWorkingCopy}
     * @param wc
     * @since 3.6
     */
    protected void doSetDefaults(ILaunchConfigurationWorkingCopy wc) {
        try {
            ILaunchConfigurationTabGroup tabGroup = LaunchConfigurationPresentationManager.getDefault()
                    .getTabGroup(wc, getMode());
            // this only works because this action is only present when the dialog is open
            ILaunchConfigurationDialog dialog = LaunchConfigurationsDialog
                    .getCurrentlyVisibleLaunchConfigurationDialog();
            tabGroup.createTabs(dialog, dialog.getMode());
            ILaunchConfigurationTab[] tabs = tabGroup.getTabs();
            for (int i = 0; i < tabs.length; i++) {
                tabs[i].setLaunchConfigurationDialog(dialog);
            }
            tabGroup.setDefaults(wc);
            tabGroup.dispose();
        } catch (CoreException e) {
            DebugUIPlugin.log(e.getStatus());
        }
    }

    /**
     * Performs initialization of the content by setting the initial tree selection
     */
    protected void initializeContent() {
        if (fSetDefaultOnOpen) {
            try {
                Object o = fInitialSelection.getFirstElement();
                if (o instanceof ILaunchConfigurationWorkingCopy) {
                    ILaunchConfigurationWorkingCopy wc = (ILaunchConfigurationWorkingCopy) o;
                    doSetDefaults(wc);
                    setInitialSelection(new StructuredSelection(wc.doSave()));
                }
            } catch (CoreException e) {
                DebugUIPlugin.log(e);
            }
        }
        doInitialTreeSelection();

        IStatus status = getInitialStatus();
        if (status != null) {
            handleStatus(status);
        }
        restoreExpansion();
    }

    /**
     * Compares two objects to determine their equality
     * 
     * @param o1 the first object
     * @param o2 the object to compare to object one
     * @return true if they are equal, false if object 1 is null, the result of o1.equals(o2) otherwise
     */
    protected boolean isEqual(Object o1, Object o2) {
        if (o1 == o2) {
            return true;
        } else if (o1 == null) {
            return false;
        } else {
            return o1.equals(o2);
        }
    }

    /**
     * Returns whether the dialog can be closed
     * 
     * @return whether the dialog can be closed
     */
    protected boolean isSafeToClose() {
        return fActiveRunningOperations == 0;
    }

    /**
     * Determine the initial configuration for this dialog.
     * Open the dialog in the mode set using #setOpenMode(int) and return one of
     * <code>Window. OK</code> or <code>Window.CANCEL</code>.
     * 
     * @see org.eclipse.jface.window.Window#open()
     * @return the int status of opening the dialog
     */
    public int open() {
        int mode = getOpenMode();
        setCurrentlyVisibleLaunchConfigurationDialog(this);
        if (mode == LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_LAST_LAUNCHED) {
            ILaunchConfiguration lastLaunchedConfig = getLastLaunchedWorkbenchConfiguration();
            if (lastLaunchedConfig != null) {
                setInitialSelection(new StructuredSelection(lastLaunchedConfig));
            }
        }
        return super.open();
    }

    /**
     * saves which of the nodes are expanded at the time the dialog is closed
     * @since 3.2
     */
    protected void persistExpansion() {
        if (fLaunchConfigurationView != null) {
            IDialogSettings settings = getDialogSettings();
            TreeItem[] items = fLaunchConfigurationView.getTreeViewer().getTree().getItems();
            String value = settings.get(DIALOG_EXPANDED_NODES);
            if (value == null) {
                value = IInternalDebugCoreConstants.EMPTY_STRING;
            }
            ArrayList list = new ArrayList();
            String[] persisted = value.split(DELIMITER);
            for (int i = 0; i < persisted.length; i++) {
                list.add(persisted[i]);
            }
            String type = IInternalDebugCoreConstants.EMPTY_STRING;
            //if the item is not in the list and is expanded add it, otherwise if it
            //is not expanded do a remove...either way for the else we query the list
            for (int i = 0; i < items.length; i++) {
                type = ((ILaunchConfigurationType) items[i].getData()).getIdentifier();
                if (!list.contains(type) & items[i].getExpanded()) {
                    list.add(type);
                } else if (!items[i].getExpanded()) {
                    list.remove(type);
                }
            }
            value = IInternalDebugCoreConstants.EMPTY_STRING;
            //build the preference string
            for (Iterator iter = list.iterator(); iter.hasNext();) {
                value += iter.next() + DELIMITER;
            }
            settings.put(DIALOG_EXPANDED_NODES, value);
        }
    }

    /**
     * Restore the original expansion state of the nodes in the viewer
     * @since 3.2
     */
    protected void restoreExpansion() {
        if (fLaunchConfigurationView != null) {
            IDialogSettings settings = getDialogSettings();
            String value = settings.get(DIALOG_EXPANDED_NODES);
            if (value != null) {
                String[] nodes = value.split(DELIMITER);
                TreeItem[] items = fLaunchConfigurationView.getTreeViewer().getTree().getItems();
                HashSet toexpand = new HashSet();
                // if we have a selection make sure it is expanded
                if (fInitialSelection != null && !fInitialSelection.isEmpty()) {
                    Object obj = fInitialSelection.getFirstElement();
                    if (obj instanceof ILaunchConfigurationType) {
                        toexpand.add(obj);
                    } else if (obj instanceof ILaunchConfiguration) {
                        try {
                            toexpand.add(((ILaunchConfiguration) obj).getType());
                        } catch (CoreException e) {
                            DebugUIPlugin.log(e);
                        }
                    }
                }
                for (int i = 0; i < nodes.length; i++) {
                    for (int k = 0; k < items.length; k++) {
                        ILaunchConfigurationType type = (ILaunchConfigurationType) items[k].getData();
                        if (type.getIdentifier().equals(nodes[i])) {
                            toexpand.add(type);
                        }
                    }
                }
                fLaunchConfigurationView.getTreeViewer().setExpandedElements(toexpand.toArray());
            }
        }
    }

    /**
     * Save the current sash weights
     */
    protected void persistSashWeights() {
        IDialogSettings settings = getDialogSettings();
        if (fSashForm != null) {
            int[] sashWeights = fSashForm.getWeights();
            settings.put(DIALOG_SASH_WEIGHTS_1, (sashWeights[0] < 10 ? DEFAULT_SASH_WEIGHTS[0] : sashWeights[0]));
            settings.put(DIALOG_SASH_WEIGHTS_2, (sashWeights[1] < 10 ? DEFAULT_SASH_WEIGHTS[1] : sashWeights[1]));
        }
    }

    /**
     * Update buttons and message.
     */
    protected void refreshStatus() {
        updateMessage();
        updateButtons();
    }

    /**
     * resize the dialog to show all relevant content
     */
    protected void resize() {
        if (getTabGroup() != null) {
            Point shell = getShell().getSize();
            int maxx = (int) (getDisplay().getBounds().width * MAX_DIALOG_WIDTH_PERCENT),
                    maxy = (int) (getDisplay().getBounds().height * MAX_DIALOG_HEIGHT_PERCENT);
            maxx = (maxx < DEFAULT_INITIAL_DIALOG_SIZE.x ? DEFAULT_INITIAL_DIALOG_SIZE.x : maxx);
            maxy = (maxy < DEFAULT_INITIAL_DIALOG_SIZE.y ? DEFAULT_INITIAL_DIALOG_SIZE.y : maxy);
            Point psize = getShell().computeSize(SWT.DEFAULT, maxy);
            if ((psize.x > maxx ? maxx : psize.x) > shell.x || (psize.y > maxy ? maxy : psize.y) > shell.y) {
                setShellSize(Math.min(psize.x, maxx), Math.min(psize.y, maxy));
                constrainShellSize();
            }
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.operation.IRunnableContext#run(boolean, boolean, org.eclipse.jface.operation.IRunnableWithProgress)
     */
    public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable)
            throws InvocationTargetException, InterruptedException {
        if (getShell() != null && getShell().isVisible()) {
            // Save focus control
            fLastControl = getShell().getDisplay().getFocusControl();
            if (fLastControl != null && fLastControl.getShell() != getShell()) {
                fLastControl = null;
            }
            // Attach the progress monitor part to the cancel button
            fProgressMonitorPart.attachToCancelComponent(null);
            fProgressMonitorPart.getParent().setVisible(true);
            fActiveRunningOperations++;

            //do work here collecting enabled states, otherwise to get these states we would need to
            //perform the validation of the dialog again, which is expensive and would cause flashing of widgets.
            Control[] children = ((Composite) fButtonComp.getChildren()[0]).getChildren();
            boolean[] prev = new boolean[children.length + 2];
            prev[0] = fTabViewer.getApplyButton().isEnabled();
            prev[1] = fTabViewer.getRevertButton().isEnabled();
            for (int i = 0; i < children.length; i++) {
                prev[i + 2] = children[i].isEnabled();
            }
            try {
                updateRunnnableControls(false, prev);
                ModalContext.run(runnable, fork, fProgressMonitorPart, getShell().getDisplay());
            } finally {
                fActiveRunningOperations--;
                updateRunnnableControls(true, prev);
                if (getShell() != null) {
                    fProgressMonitorPart.getParent().setVisible(false);
                    fProgressMonitorPart.removeFromCancelComponent(null);
                    if (fLastControl != null) {
                        fLastControl.setFocus();
                    }
                }
            }
        } else {
            PlatformUI.getWorkbench().getProgressService().run(fork, cancelable, runnable);
        }
    }

    /**
     * Updates the enablement of the runnable controls to appear disabled as a job is running
     * @param enabled the desired enable status of the dialog area, revert//apply buttons, and
     * @param prev the previous settings for the apply and revert buttons to be reset to, only takes effect if enable is set to true
     * any children of the button bar
     * @since 3.3.0
     */
    private void updateRunnnableControls(boolean enabled, boolean[] prev) {
        fTabViewer.getApplyButton().setEnabled(enabled ? prev[0] : enabled);
        fTabViewer.getRevertButton().setEnabled(enabled ? prev[1] : enabled);
        //the arrangement never differs: button comp has one child that holds all the buttons
        Control[] children = ((Composite) fButtonComp.getChildren()[0]).getChildren();
        for (int i = 0; i < children.length; i++) {
            children[i].setEnabled(enabled ? prev[i + 2] : enabled);
        }
        getDialogArea().setEnabled(enabled);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationDialog#setActiveTab(org.eclipse.debug.ui.ILaunchConfigurationTab)
     */
    public void setActiveTab(ILaunchConfigurationTab tab) {
        fTabViewer.setActiveTab(tab);
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationDialog#setActiveTab(int)
     */
    public void setActiveTab(int index) {
        fTabViewer.setActiveTab(index);
    }

    /**
     * Sets the initial selection for the dialog when opened in
     * <code>LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_SELECTION</code> mode.
     */
    public void setInitialSelection(IStructuredSelection selection) {
        fInitialSelection = selection;
    }

    /**
     * Sets the status to open the dialog on.
     * 
     * @param status the initial status for the dialog
     */
    public void setInitialStatus(IStatus status) {
        fInitialStatus = status;
    }

    /**
     * Sets whether the tab group should set default values in the launch configuration
     * when the dialog is opened. If this method is not called, default values are not
     * set.
     * 
     * @param setDefaults whether to set default values
     * @since 3.6
     */
    public void setDefaultsOnOpen(boolean setDefaults) {
        fSetDefaultOnOpen = setDefaults;
    }

    /**
     * Returns if the dialog is supposed to be setting the default values for
     * the initial configuration when it opens
     * 
     * @return <code>true</code> if the defaults should be set on open, <code>false</code> otherwise
     * @since 3.6
     */
    public boolean shouldSetDefaultsOnOpen() {
        return fSetDefaultOnOpen;
    }

    /**
     * Sets the launch group to display.
     * 
     * @param group launch group
     */
    protected void setLaunchGroup(LaunchGroupExtension group) {
        fGroup = group;
    }

    /**
     * Set the title area image based on the mode this dialog was initialized with
     */
    protected void setModeLabelState() {
        setTitleImage(getBannerImage());
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationDialog#setName(java.lang.String)
     */
    public void setName(String name) {
        fTabViewer.setName(name);
    }

    /**
     * Returns the current launch manager
     * @return the current launch manager
     */
    protected ILaunchManager getLaunchManager() {
        return DebugPlugin.getDefault().getLaunchManager();
    }

    /**
     * Set the flag indicating how this dialog behaves when the <code>open()</code> method is called.
     * Valid values are defined by the LAUNCH_CONFIGURATION_DIALOG... constants in this class.
     */
    public void setOpenMode(int mode) {
        fOpenMode = mode;
    }

    /**
      * Increase the size of this dialog's <code>Shell</code> by the specified amounts.
      * Do not increase the size of the Shell beyond the bounds of the Display.
      */
    protected void setShellSize(int width, int height) {
        Rectangle bounds = getShell().getMonitor().getBounds();
        getShell().setSize(Math.min(width, bounds.width), Math.min(height, bounds.height));
    }

    /**
     * Sets the viewer used to display the tabs for a launch configuration.
     * 
     * @param viewer the new view to set
     */
    protected void setTabViewer(LaunchConfigurationTabGroupViewer viewer) {
        fTabViewer = viewer;
    }

    /**
     * Create and return a dialog that asks the user whether they want to discard
     * unsaved changes.
     * 
     * @return the return code based on the button selected.
     * The value will be one of <code>YES_ID</code> or <code>NO_ID</code> from
     * <code>IDialogConstants</code>.
     */
    private int showDiscardChangesDialog() {
        StringBuffer buffer = new StringBuffer(
                MessageFormat.format(LaunchConfigurationsMessages.LaunchConfigurationDialog_The_configuration___35,
                        new String[] { fTabViewer.getWorkingCopy().getName() }));
        buffer.append(fTabViewer.getErrorMesssage());
        buffer.append(LaunchConfigurationsMessages.LaunchConfigurationDialog_Do_you_wish_to_discard_changes_37);
        MessageDialog dialog = new MessageDialog(getShell(),
                LaunchConfigurationsMessages.LaunchConfigurationDialog_Discard_changes__38, null, buffer.toString(),
                MessageDialog.QUESTION,
                new String[] { LaunchConfigurationsMessages.LaunchConfigurationDialog_Yes_32,
                        LaunchConfigurationsMessages.LaunchConfigurationDialog_No_33 },
                1);
        int val = IDialogConstants.NO_ID;
        if (dialog.open() == 0) {
            if (fLaunchConfigurationView != null) {
                fLaunchConfigurationView.setAutoSelect(false);
            }
            fTabViewer.handleRevertPressed();
            val = IDialogConstants.YES_ID;
            if (fLaunchConfigurationView != null) {
                fLaunchConfigurationView.setAutoSelect(true);
            }
        }
        if (val == IDialogConstants.NO_ID) {
            val = ID_DISCARD_BUTTON;
        }
        return val;
    }

    /**
     * Create and return a dialog that asks the user whether they want to save
     * unsaved changes.
     * 
     * @return the return code based on the button selected.
     * The value will be one of <code>YES_ID</code>, <code>NO_ID</code>, or <code>CANCEL_ID</code>, from
     * <code>IDialogConstants</code>.
     */
    private int showSaveChangesDialog() {
        String message = MessageFormat.format(
                LaunchConfigurationsMessages.LaunchConfigurationDialog_The_configuration___29,
                new String[] { fTabViewer.getWorkingCopy().getName() });
        MessageDialog dialog = new MessageDialog(getShell(),
                LaunchConfigurationsMessages.LaunchConfigurationFilteredTree_save_changes, null, message,
                MessageDialog.QUESTION,
                new String[] { LaunchConfigurationsMessages.LaunchConfigurationDialog_Yes_32,
                        LaunchConfigurationsMessages.LaunchConfigurationDialog_No_33,
                        LaunchConfigurationsMessages.LaunchConfigurationsDialog_c_ancel },
                0);
        int ret = dialog.open();
        int val = IDialogConstants.CANCEL_ID;
        if (ret == 0 || ret == 1) {
            if (ret == 0) {
                val = IDialogConstants.YES_ID;
            } else {
                val = IDialogConstants.NO_ID;
            }
        }
        return val;
    }

    /**
     * Show the user a dialog appropriate to whether the unsaved changes in the current config
     * can be saved or not.  Return <code>true</code> if the user indicated that they wish to replace
     * the current config, either by saving changes or by discarding the, return <code>false</code>
     * otherwise.
     * 
     * @return returns the <code>showSaveChangesDialog</code> return value
     */
    private int showUnsavedChangesDialog() {
        if (fTabViewer.canSave()) {
            return showSaveChangesDialog();
        }
        return showDiscardChangesDialog();
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationDialog#updateButtons()
     */
    public void updateButtons() {
        if (!fSettingInput) {
            // New, Delete, & Duplicate toolbar actions
            getNewAction().setEnabled(getNewAction().isEnabled());
            getDeleteAction().setEnabled(getDeleteAction().isEnabled());
            getDuplicateAction().setEnabled(getDuplicateAction().isEnabled());
            fTabViewer.refresh();
            getButton(ID_LAUNCH_BUTTON).setEnabled(
                    fTabViewer.canLaunch() & fTabViewer.canLaunchWithModes() & !fTabViewer.hasDuplicateDelegates());
        } else {
            fTabViewer.refresh();
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.debug.ui.ILaunchConfigurationDialog#updateMessage()
     */
    public void updateMessage() {
        if (!fSettingInput) {
            setErrorMessage(fTabViewer.getErrorMesssage());
            setMessage(fTabViewer.getMessage());
        }
    }

    /**
     * Returns if there is a selection in the tree viewer or not
     * @return true if something in the tree is selected, false otherwise
     * @since 3.2
     */
    public boolean isTreeSelectionEmpty() {
        return fLaunchConfigurationView.getTreeViewer().getSelection().isEmpty();
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
     */
    public void propertyChange(final PropertyChangeEvent event) {
        WorkbenchJob job = new WorkbenchJob(IInternalDebugCoreConstants.EMPTY_STRING) {
            public IStatus runInUIThread(IProgressMonitor monitor) {
                TreeViewer viewer = fLaunchConfigurationView.getTreeViewer();
                boolean newvalue = Boolean.valueOf(event.getNewValue().toString()).booleanValue();
                if (event.getProperty().equals(IInternalDebugUIConstants.PREF_FILTER_LAUNCH_CLOSED)) {
                    updateFilter(newvalue, fClosedProjectFilter);
                } else if (event.getProperty().equals(IInternalDebugUIConstants.PREF_FILTER_LAUNCH_DELETED)) {
                    updateFilter(newvalue, fDeletedProjectFilter);
                } else if (event.getProperty().equals(IInternalDebugUIConstants.PREF_FILTER_LAUNCH_TYPES)) {
                    updateFilter(newvalue, fLCTFilter);
                } else if (event.getProperty().equals(IInternalDebugUIConstants.PREF_FILTER_WORKING_SETS)) {
                    updateFilter(newvalue, fWorkingSetsFilter);
                } else if (event.getProperty().equals(IInternalDebugUIConstants.PREF_FILTER_TYPE_LIST)) {
                    if (DebugUIPlugin.getDefault().getPreferenceStore()
                            .getBoolean(IInternalDebugUIConstants.PREF_FILTER_LAUNCH_TYPES)) {
                        viewer.refresh();
                        fLaunchConfigurationView.updateFilterLabel();
                    }
                }

                return Status.OK_STATUS;
            }
        };
        job.runInUIThread(new NullProgressMonitor());
    }

    /**
     * Updates the state of a filter based on the state variable
     * @param state if the filter needs to be added or removed, true indicates add, false indicates remove
     * @param filter the filter to update
     */
    private void updateFilter(boolean state, ViewerFilter filter) {
        TreeViewer viewer = (TreeViewer) fLaunchConfigurationView.getViewer();
        if (state) {
            viewer.addFilter(filter);
        } else {
            viewer.removeFilter(filter);
        }
        fLaunchConfigurationView.updateFilterLabel();
    }
}