diff options
author | Darin Wright | 2002-11-21 16:41:53 +0000 |
---|---|---|
committer | Darin Wright | 2002-11-21 16:41:53 +0000 |
commit | 17dfba30565cd64599266cd080fc0d539142c370 (patch) | |
tree | bfe4c9fbce3f9739b3578d5de0c53b307e14639f /org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsDialog.java | |
parent | c74282fb4de2518e5958122850b661b66f139c25 (diff) | |
download | eclipse.platform.debug-17dfba30565cd64599266cd080fc0d539142c370.tar.gz eclipse.platform.debug-17dfba30565cd64599266cd080fc0d539142c370.tar.xz eclipse.platform.debug-17dfba30565cd64599266cd080fc0d539142c370.zip |
bug 19674 - refactor LCD
Diffstat (limited to 'org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsDialog.java')
-rw-r--r-- | org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsDialog.java | 1748 |
1 files changed, 1748 insertions, 0 deletions
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsDialog.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsDialog.java new file mode 100644 index 000000000..96552fe28 --- /dev/null +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsDialog.java @@ -0,0 +1,1748 @@ +package org.eclipse.debug.internal.ui.launchConfigurations; + +/********************************************************************** +Copyright (c) 2000, 2002 IBM Corp. All rights reserved. +This file is 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 +**********************************************************************/ + +import java.lang.reflect.InvocationTargetException; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationType; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.debug.internal.ui.IDebugHelpContextIds; +import org.eclipse.debug.internal.ui.PixelConverter; +import org.eclipse.debug.internal.ui.SWTUtil; +import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants; +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.dialogs.ControlEnableState; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.dialogs.ProgressMonitorDialog; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.operation.ModalContext; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.wizard.ProgressMonitorPart; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Cursor; +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.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.IWorkingSetManager; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.help.WorkbenchHelp; + + +/** + * The dialog used to edit and launch launch configurations. + */ +public class LaunchConfigurationsDialog extends TitleAreaDialog implements ILaunchConfigurationDialog { + + /** + * Keep track of the currently visible dialog instance
*/ + private static ILaunchConfigurationDialog fgCurrentlyVisibleLaunchConfigurationDialog; + + /** + * The label appearing above tree of configs & config types. + */ + private Label fTreeLabel; + + /** + * The workbench context present when this dialog is opened. + */ + private Object fContext; + + /** + * The Composite used to insert an adjustable 'sash' between the tree and the tabs. + */ + private SashForm fSashForm; + + /** + * Default weights for the SashForm that specify how wide the selection and + * edit areas aree relative to each other. + */ + private static final int[] DEFAULT_SASH_WEIGHTS = new int[] {11, 30}; + + /** + * The launch configuration selection area. + */ + private Composite fSelectionArea; + + /** + * Tree view of launch configurations + */ + private LaunchConfigurationView fLaunchConfigurationView; + + /** + * Tab edit area + */ + private LaunchConfigurationTabGroupViewer fTabViewer; + + /** + * True while setting the input to the tab viewer + */ + private boolean fInitializingTabs; + + /** + * The launch configuration edit area. + */ + private Composite fEditArea; + + /** + * The 'New configuration' action. + */ + private ButtonAction fButtonActionNew; + + /** + * The 'Delete configuration' action. + */ + private ButtonAction fButtonActionDelete; + + /** + * The 'cancel' button that appears when the in-dialog progress monitor is shown. + */ + private Button fProgressMonitorCancelButton; + + /** + * Flag indicating if the progress monitor part's Cancel button has been pressed. + */ + private boolean fCancelButtonPressed; + + /** + * Clients of this dialog may set an 'initial configuration type', which means that when + * the dialog is opened, a configuration of that type will be created, initialized, and + * saved. Note that the initial config type is ignored if single-click launching is enabled. + */ + private ILaunchConfigurationType fInitialConfigType; + + /** + * 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; + + private ProgressMonitorPart fProgressMonitorPart; + private Cursor waitCursor; + private Cursor arrowCursor; + private MessageDialog fWindowClosingDialog; + + /** + * The number of 'long-running' operations currently taking place in this dialog + */ + private long fActiveRunningOperations = 0; + + /** + * The launch groupd being displayed + */ + private LaunchGroupExtension fGroup; + + /** + * Banner image + */ + private Image fBannerImage; + + /** + * Double-click action + */ + private IAction fDoubleClickAction; + + /** + * 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; + + /** + * Constrant String used as key for setting and retrieving current Control with focus + */ + private static final String FOCUS_CONTROL = "focusControl";//$NON-NLS-1$ + + /** + * The height in pixels of this dialog's progress indicator + */ + private static int PROGRESS_INDICATOR_HEIGHT = 18; + + /** + * 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. + */ + private static final float MAX_DIALOG_WIDTH_PERCENT = 0.75f; + + /** + * Empty array + */ + protected static final Object[] EMPTY_ARRAY = new Object[0]; + + protected static final String DEFAULT_NEW_CONFIG_NAME = LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.New_configuration_1"); //$NON-NLS-1$ + + /** + * Size of this dialog if there is no preference specifying a size. + */ + protected static final Point DEFAULT_INITIAL_DIALOG_SIZE = new Point(620, 560); + + /** + * Status area messages + */ + protected static final String LAUNCH_STATUS_OK_MESSAGE = LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Ready_to_launch_2"); //$NON-NLS-1$ + protected static final String LAUNCH_STATUS_STARTING_FROM_SCRATCH_MESSAGE + = LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Select_a_configuration_to_launch_or_a_config_type_to_create_a_new_configuration_3"); //$NON-NLS-1$ + + /** + * Constant specifying that the launch configuration dialog should not actually open, + * but instead should attempt to re-launch the last configuration that was sucessfully + * launched in the workspace. If there is no last launched configuration, just open the dialog. + */ + public static final int LAUNCH_CONFIGURATION_DIALOG_LAUNCH_LAST = 0; + + /** + * 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; + + /** + * 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_LAUNCH_LAST; + + /** + * Constructs a new launch configuration dialog on the given + * parent shell. + * + * @param shell the parent shell + * @param selection the selection used to initialize this dialog, typically the + * current workbench selection + * @param mode one of <code>ILaunchManager.RUN_MODE</code> or + * <code>ILaunchManager.DEBUG_MODE</code> + */ + public LaunchConfigurationsDialog(Shell shell, IStructuredSelection selection, LaunchGroupExtension group) { + super(shell); + setShellStyle(getShellStyle() | SWT.RESIZE); + setLaunchGroup(group); + } + + /** + * 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; + } + + protected int getOpenMode() { + return fOpenMode; + } + + /** + * 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(Composite) + */ + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, ID_LAUNCH_BUTTON, getLaunchButtonText(), true); + createButton(parent, ID_CLOSE_BUTTON, LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Close_1"), false); //$NON-NLS-1$ + } + + /** + * Handle the 'save and launch' & 'launch' buttons here, all others are handled + * in <code>Dialog</code> + * + * @see 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); + } + } + + /** + * Returns the appropriate text for the launch button - run or debug. + */ + private String getLaunchButtonText() { + if (getMode().equals(ILaunchManager.DEBUG_MODE)) { + return LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Deb&ug_4"); //$NON-NLS-1$ + } else { + return LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.R&un_5"); //$NON-NLS-1$ + } + } + + /** + * @see Dialog#createContents(Composite) + */ + protected Control createContents(Composite parent) { + Control contents = super.createContents(parent); + initializeBounds(); + initializeSashForm(); + ensureSelectionAreaWidth(); + initializeWorkingSet(); + doInitialTreeSelection(); + return contents; + } + + /** + * Initialize the relative weights (widths) of the 2 sides of the sash. + */ + private void initializeSashForm() { + int[] sashWeights = DEFAULT_SASH_WEIGHTS; + String sashWeightString = getPreferenceStore().getString(IDebugPreferenceConstants.PREF_LAUNCH_CONFIGURATION_DIALOG_SASH_WEIGHTS); + if (sashWeightString.length() > 0) { + Point sashWeightPoint = parseCoordinates(sashWeightString); + if (sashWeightPoint != null) { + sashWeights[0] = sashWeightPoint.x; + sashWeights[1] = sashWeightPoint.y; + } + } + getSashForm().setWeights(sashWeights); + } + + /** + * Retrieve the last working set in use and apply it to the tree. + */ + private void initializeWorkingSet() { + String workingSetName = getPreferenceStore().getString(IDebugPreferenceConstants.PREF_LAUNCH_CONFIGURATION_DIALOG_WORKING_SET_NAME); + IWorkingSet workingSet = getWorkingSetManager().getWorkingSet(workingSetName); + if (workingSet != null) { + getWorkingSetActionManager().setWorkingSet(workingSet, true); + } + } + + /** + * Check if the selection area is currently wide enough so that both the 'New' & + * 'Delete' buttons are shown without truncation. If so, do nothing. Otherwise, + * increase the width of this dialog's Shell just enough so that both buttons + * are shown cleanly. + */ + private void ensureSelectionAreaWidth() { + Button newButton = getButtonActionNew().getButton(); + Button deleteButton = getButtonActionDelete().getButton(); + int requiredWidth = newButton.getBounds().width + deleteButton.getBounds().width; + int marginWidth = ((GridLayout)getSelectionArea().getLayout()).marginWidth; + int horizontalSpacing = ((GridLayout)getSelectionArea().getLayout()).horizontalSpacing; + requiredWidth += (2 * marginWidth) + horizontalSpacing; + int currentWidth = getSelectionArea().getBounds().width; + + if (requiredWidth > currentWidth) { + int[] newSashWeights = new int[2]; + newSashWeights[0] = requiredWidth; + newSashWeights[1] = getEditArea().getBounds().width; + Shell shell= getShell(); + Point shellSize= shell.getSize(); + setShellSize(shellSize.x + (requiredWidth - currentWidth), shellSize.y); + getSashForm().setWeights(newSashWeights); + } + } + + /** + * Set the initial selection in the tree. + */ + public void doInitialTreeSelection() { + fLaunchConfigurationView.getViewer().setSelection(getInitialSelection()); + } + + /** + * Write out this dialog's Shell size, location & sash weights to the preference store. + */ + private void persistShellGeometry() { + Point shellLocation = getShell().getLocation(); + Point shellSize = getShell().getSize(); + int[] sashWeights = getSashForm().getWeights(); + String locationString = serializeCoords(shellLocation); + String sizeString = serializeCoords(shellSize); + String sashWeightString = serializeCoords(new Point(sashWeights[0], sashWeights[1])); + getPreferenceStore().setValue(IDebugPreferenceConstants.PREF_LAUNCH_CONFIGURATION_DIALOG_LOCATION, locationString); + getPreferenceStore().setValue(IDebugPreferenceConstants.PREF_LAUNCH_CONFIGURATION_DIALOG_SIZE, sizeString); + getPreferenceStore().setValue(IDebugPreferenceConstants.PREF_LAUNCH_CONFIGURATION_DIALOG_SASH_WEIGHTS, sashWeightString); + } + + /** + * Store the current working set. + */ + private void persistWorkingSet() { + IWorkingSet workingSet = getWorkingSetActionManager().getWorkingSet(); + if (workingSet != null) { + getPreferenceStore().setValue(IDebugPreferenceConstants.PREF_LAUNCH_CONFIGURATION_DIALOG_WORKING_SET_NAME, workingSet.getName()); + } else { + getPreferenceStore().setToDefault(IDebugPreferenceConstants.PREF_LAUNCH_CONFIGURATION_DIALOG_WORKING_SET_NAME); + } + } + + /** + * @see Window#close() + */ + public boolean close() { + persistShellGeometry(); + persistWorkingSet(); + setCurrentlyVisibleLaunchConfigurationDialog(null); + getBannerImage().dispose(); + fTabViewer.dispose(); + fLaunchConfigurationView.dispose(); + return super.close(); + } + + /** + * Determine the first configuration for this dialog. If single-click launching is + * enabled, launch the configuration WITHOUT realizing the dialog. If single-click + * launching was successful, this method returns + * <code>ILaunchConfigurationDialog.SINGLE_CLICK_LAUNCHED</code>. Otherwise, open the + * dialog in the specified mode. + * + * @see Window#open() + */ + public int open() { + int mode = getOpenMode(); + if (mode == LAUNCH_CONFIGURATION_DIALOG_LAUNCH_LAST) { + return doLastLaunchedConfig(true); + } else if (mode == LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_LAST_LAUNCHED) { + return doLastLaunchedConfig(false); + } else if (mode == LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_SELECTION) { + return openDialogOnSelection(); + } + return super.open(); + } + + /** + * Retrieve the last launched configuration in the workspace. If <code>launch</code> + * is <code>true</code>, launch this configuration without showing the dialog, otherwise + * just set the initial selection in the dialog to the last launched configuration. + */ + protected int doLastLaunchedConfig(boolean launch) { + ILaunchConfiguration lastLaunchedConfig = getLastLaunchedWorkbenchConfiguration(); + if (launch) { + try { + if (lastLaunchedConfig != null) { + if (lastLaunchedConfig.supportsMode(getMode())) { + doLaunch(lastLaunchedConfig); + } else { + // If we're trying to launch, but the last launched config doesn't + // support the current mode of the dialog, show an error dialog + String configName = lastLaunchedConfig.getName(); + String title = LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Cannot_relaunch_1"); //$NON-NLS-1$ + String message = MessageFormat.format(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Cannot_relaunch_[{1}]_because_it_does_not_support_{2}_mode_2"), new String[] {configName, getMode()}); //$NON-NLS-1$ + MessageDialog.openError(getShell(), title, message); + } + return ILaunchConfigurationDialog.LAUNCHED_BEFORE_OPENING; + } + } catch(CoreException e) { + DebugUIPlugin.errorDialog(DebugUIPlugin.getShell(), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Launch_Configuration_Error_6"), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Exception_occurred_processing_launch_configuration._See_log_for_more_information_7"), e); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + setCurrentlyVisibleLaunchConfigurationDialog(this); + if (lastLaunchedConfig != null) { + setInitialSelection(new StructuredSelection(lastLaunchedConfig)); + } + return super.open(); + } + + /** + * Open this dialog with the selection set to the value specified by + * <code>setInitialSelection()</code>. + */ + protected int openDialogOnSelection() { + // Nothing special is required, the dialog will open and whatever was specified + // via setInitialSelection() will be selected in the tree + setCurrentlyVisibleLaunchConfigurationDialog(this); + return super.open(); + } + + /** + * Return the last launched configuration in the workspace. + */ + protected ILaunchConfiguration getLastLaunchedWorkbenchConfiguration() { + return DebugUIPlugin.getLaunchConfigurationManager().getLastLaunch(getLaunchGroup().getIdentifier()); + } + + /** + * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(Composite) + */ + protected Control createDialogArea(Composite parent) { + GridData gd; + Composite dialogComp = (Composite)super.createDialogArea(parent); + Composite topComp = new Composite(dialogComp, SWT.NONE); + gd = new GridData(GridData.FILL_BOTH); + topComp.setLayoutData(gd); + GridLayout topLayout = new GridLayout(); + topLayout.numColumns = 2; + topLayout.marginHeight = 5; + topLayout.marginWidth = 0; + topComp.setLayout(topLayout); + + // Set the things that TitleAreaDialog takes care of + setTitle(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Create,_manage,_and_run_launch_configurations_8")); //$NON-NLS-1$ + setMessage(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Ready_to_launch_2")); //$NON-NLS-1$ + setModeLabelState(); + + // Create the SashForm that contains the selection area on the left, + // and the edit area on the right + setSashForm(new SashForm(topComp, SWT.NONE)); + getSashForm().setOrientation(SWT.HORIZONTAL); + gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 2; + getSashForm().setLayoutData(gd); + + // Build the launch configuration selection area and put it into the composite. + Control launchConfigSelectionArea = createLaunchConfigurationSelectionArea(getSashForm()); + gd = new GridData(GridData.FILL_VERTICAL); + launchConfigSelectionArea.setLayoutData(gd); + + // Build the launch configuration edit area and put it into the composite. + Composite editAreaComp = createLaunchConfigurationEditArea(getSashForm()); + setEditArea(editAreaComp); + gd = new GridData(GridData.FILL_BOTH); + editAreaComp.setLayoutData(gd); + + // Build the separator line that demarcates the button bar + Label separator = new Label(topComp, SWT.HORIZONTAL | SWT.SEPARATOR); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan = 2; + separator.setLayoutData(gd); + + dialogComp.layout(true); + + return dialogComp; + } + + /** + * Set the title area image based on the mode this dialog was initialized with + */ + protected void setModeLabelState() { + setTitleImage(getBannerImage()); + } + + /** + * Update buttons and message. + */ + protected void refreshStatus() { + updateButtons(); + updateMessage(); + fTabViewer.refresh(); + } + + private Display getDisplay() { + Shell shell = getShell(); + if (shell != null) { + return shell.getDisplay(); + } else { + return Display.getDefault(); + } + } + + /** + * 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 + */ + private Control createLaunchConfigurationSelectionArea(Composite parent) { + Composite comp = new Composite(parent, SWT.NONE); + setSelectionArea(comp); + GridLayout layout = new GridLayout(); + layout.numColumns = 3; + layout.marginHeight = 0; + layout.marginWidth = 5; + comp.setLayout(layout); + + setTreeLabel(new Label(comp, SWT.NONE)); + GridData gd = new GridData(); + gd.horizontalSpan = 3; + getTreeLabel().setLayoutData(gd); + getTreeLabel().setText(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Launch_Con&figurations__1")); //$NON-NLS-1$ + // TODO: tooltip + //updateTreeLabelTooltip(); + + fLaunchConfigurationView = new LaunchConfigurationView(getLaunchGroup()); + fLaunchConfigurationView.createLaunchDialogControl(comp); + Viewer viewer = fLaunchConfigurationView.getViewer(); + Control control = viewer.getControl(); + + gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 3; + // Set width hint to 0 to force tree to only be as wide as the combined + // width of the 'New' & 'Delete' buttons. Otherwise tree wants to be much wider. + gd.widthHint = 0; + control.setLayoutData(gd); + viewer.addSelectionChangedListener(new ISelectionChangedListener() { + /** + * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) + */ + public void selectionChanged(SelectionChangedEvent event) { + handleLaunchConfigurationSelectionChanged(event); + } + }); + + fDoubleClickAction = new DoubleClickAction(); + fLaunchConfigurationView.setAction(IDebugView.DOUBLE_CLICK_ACTION, fDoubleClickAction); + + Button newButton = SWTUtil.createPushButton(comp, LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Ne&w_13"), null); //$NON-NLS-1$ + setButtonActionNew(new ButtonActionNew(newButton.getText(), newButton)); + + Button deleteButton = SWTUtil.createPushButton(comp, LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Dele&te_14"), null); //$NON-NLS-1$ + setButtonActionDelete(new ButtonActionDelete(deleteButton.getText(), deleteButton)); + + AbstractLaunchConfigurationAction.IConfirmationRequestor requestor = + new AbstractLaunchConfigurationAction.IConfirmationRequestor() { + /** + * @see org.eclipse.debug.internal.ui.launchConfigurations.AbstractLaunchConfigurationAction.IConfirmationRequestor#getConfirmation() + */ + public boolean getConfirmation() { + return canDiscardCurrentConfig(); + } + }; + + // confirmation requestors + getDuplicateAction().setConfirmationRequestor(requestor); + getNewAction().setConfirmationRequestor(requestor); + + return comp; + } + + /** + * 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 + */ + private Composite createLaunchConfigurationEditArea(Composite parent) { + fTabViewer = new LaunchConfigurationTabGroupViewer(parent, this); + fTabViewer.addSelectionChangedListener(new ISelectionChangedListener() { + /** + * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) + */ + public void selectionChanged(SelectionChangedEvent event) { + handleTabSelectionChanged(event); + } + }); + return (Composite)fTabViewer.getControl(); + } + + /** + * @see Dialog#createButtonBar(Composite) + */ + protected Control createButtonBar(Composite parent) { + Composite composite= new Composite(parent, SWT.NULL); + GridLayout layout= new GridLayout(); + layout.numColumns= 2; + layout.marginHeight= 0; + layout.marginWidth= 0; + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + GridLayout pmLayout = new GridLayout(); + pmLayout.numColumns = 3; + setProgressMonitorPart(new ProgressMonitorPart(composite, pmLayout, PROGRESS_INDICATOR_HEIGHT)); + Button cancelButton = createButton(getProgressMonitorPart(), ID_CANCEL_BUTTON, LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Cancel_3"), true); //$NON-NLS-1$ + setProgressMonitorCancelButton(cancelButton); + getProgressMonitorCancelButton().addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent evt) { + setCancelButtonPressed(true); + } + }); + getProgressMonitorPart().setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + getProgressMonitorPart().setVisible(false); + + return super.createButtonBar(composite); + } + + /** + * Sets the title for the dialog, and establishes the help context. + * + * @see org.eclipse.jface.window.Window#configureShell(Shell); + */ + protected void configureShell(Shell shell) { + super.configureShell(shell); + String title = getLaunchGroup().getLabel(); + if (title == null) { + title = LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Launch_Configurations_18"); //$NON-NLS-1$ + } + shell.setText(title); + WorkbenchHelp.setHelp( + shell, + IDebugHelpContextIds.LAUNCH_CONFIGURATION_DIALOG); + } + + /** + * @see Window#getInitialLocation(Point) + */ + protected Point getInitialLocation(Point initialSize) { + String locationString = getPreferenceStore().getString(IDebugPreferenceConstants.PREF_LAUNCH_CONFIGURATION_DIALOG_LOCATION); + if (locationString.length() > 0) { + Point locationPoint = parseCoordinates(locationString); + if (locationPoint != null) { + return locationPoint; + } + } + return super.getInitialLocation(initialSize); + } + + /** + * @see Window#getInitialSize() + */ + protected Point getInitialSize() { + String sizeString = getPreferenceStore().getString(IDebugPreferenceConstants.PREF_LAUNCH_CONFIGURATION_DIALOG_SIZE); + if (sizeString.length() > 0) { + Point sizePoint = parseCoordinates(sizeString); + if (sizePoint != null) { + return sizePoint; + } + } + return DEFAULT_INITIAL_DIALOG_SIZE; + } + + /** + * Given a coordinate String of the form "123x456" return a Point object whose + * X value is 123 and Y value is 456. Return <code>null</code> if the String + * is not in the specified form. + */ + private Point parseCoordinates(String coordString) { + int byIndex = coordString.indexOf('x'); + if (byIndex < 0) { + return null; + } + + try { + int x = Integer.parseInt(coordString.substring(0, byIndex)); + int y = Integer.parseInt(coordString.substring(byIndex + 1)); + return new Point(x, y); + } catch (NumberFormatException nfe) { + return null; + } + } + + /** + * Given a Point object, return a String of the form "XCoordxYCoord". + */ + private String serializeCoords(Point coords) { + StringBuffer buffer = new StringBuffer(); + buffer.append(coords.x); + buffer.append('x'); + buffer.append(coords.y); + return buffer.toString(); + } + + private void setSashForm(SashForm sashForm) { + fSashForm = sashForm; + } + + private SashForm getSashForm() { + return fSashForm; + } + + /** + * Returns the launch manager. + * + * @return the launch manager + */ + private ILaunchManager getLaunchManager() { + return DebugPlugin.getDefault().getLaunchManager(); + } + + private IWorkingSetManager getWorkingSetManager() { + return PlatformUI.getWorkbench().getWorkingSetManager(); + } + + /** + * Returns whether this dialog is currently open + */ + private boolean isVisible() { + return fEditArea != null; + } + + /** + * 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; + ISelection selection = event.getSelection(); + if (!selection.isEmpty()) { + if (selection instanceof IStructuredSelection) { + IStructuredSelection structuredSelection = (IStructuredSelection)selection; + if (structuredSelection.size() == 1) { + newInput = structuredSelection.getFirstElement(); + } + } + } + updateButtons(); + + if (!isEqual(input, newInput)) { + ILaunchConfigurationTabGroup group = getTabGroup(); + if (fTabViewer.isDirty() && fTabViewer.getOriginal().exists()) { + boolean canReplace = showSaveChangesDialog(); + if (!canReplace) { + // restore the original selection + IStructuredSelection sel = new StructuredSelection(fTabViewer.getOriginal()); + fLaunchConfigurationView.getViewer().setSelection(sel); + return; + } + } + setInitializingTabs(true); + fTabViewer.setInput(newInput); + setInitializingTabs(false); + refreshStatus(); + ILaunchConfigurationTabGroup newGroup = getTabGroup(); + if (!isEqual(group, newGroup)) { + resize(); + } + } + } + + protected boolean isEqual(Object o1, Object o2) { + if (o1 == o2) { + return true; + } else if (o1 == null) { + return false; + } else { + return o1.equals(o2); + } + } + + + protected void resize() { + // determine the maximum tab dimensions + PixelConverter pixelConverter = new PixelConverter(getEditArea()); + int runningTabWidth = 0; + ILaunchConfigurationTabGroup group = getTabGroup(); + if (group == null) { + return; + } + ILaunchConfigurationTab[] tabs = group.getTabs(); + Point contentSize = new Point(0, 0); + for (int i = 0; i < tabs.length; i++) { + String name = tabs[i].getName(); + Image image = tabs[i].getImage(); + runningTabWidth += pixelConverter.convertWidthInCharsToPixels(name.length() + 5); + if (image != null) { + runningTabWidth += image.getBounds().width; + } + Control control = tabs[i].getControl(); + if (control != null) { + Point size = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); + if (size.x > contentSize.x) { + contentSize.x = size.x; + } + if (size.y > contentSize.y) { + contentSize.y = size.y; + } + } + } + + // Determine if more space is needed to show all tab labels across the top of the + // tab folder. If so, only increase size of dialog to some percent of the available + // screen real estate. + if (runningTabWidth > contentSize.x) { + int maxAllowedWidth = (int) (getDisplay().getBounds().width * MAX_DIALOG_WIDTH_PERCENT); + int otherWidth = getSashForm().SASH_WIDTH + getSelectionArea().getBounds().width; + int totalWidth = runningTabWidth + otherWidth; + if (totalWidth > maxAllowedWidth) { + contentSize.x = maxAllowedWidth - otherWidth; + } else { + contentSize.x = runningTabWidth; + } + } + + // Adjust the maximum tab dimensions to account for the extra space required for the tab labels + Rectangle tabFolderBoundingBox = getEditArea().computeTrim(0, 0, contentSize.x, contentSize.y); + contentSize.x = tabFolderBoundingBox.width; + contentSize.y = tabFolderBoundingBox.height; + + // Force recalculation of sizes + getEditArea().layout(true); + + // Calculate difference between required space for tab folder and current size, + // then increase size of this dialog's Shell by that amount + Rectangle rect = getEditArea().getClientArea(); + Point containerSize= new Point(rect.width, rect.height); + int hdiff= contentSize.x - containerSize.x; + int vdiff= contentSize.y - containerSize.y; + // Only increase size of dialog, never shrink it + if (hdiff > 0 || vdiff > 0) { + int[] newSashWeights = null; + if (hdiff > 0) { + newSashWeights = calculateNewSashWeights(hdiff); + } + hdiff= Math.max(0, hdiff); + vdiff= Math.max(0, vdiff); + Shell shell= getShell(); + Point shellSize= shell.getSize(); + setShellSize(shellSize.x + hdiff, shellSize.y + vdiff); + // Adjust the sash weights so that all of the increase in width + // is given to the tab area + if (newSashWeights != null) { + getSashForm().setWeights(newSashWeights); + } + } + } + + /** + * Notification that tab selection has changed. + * + * @param event selection changed event + */ + protected void handleTabSelectionChanged(SelectionChangedEvent event) { + refreshStatus(); + } + + private void setInitializingTabs(boolean init) { + fInitializingTabs = init; + } + + private boolean isInitializingTabs() { + return fInitializingTabs; + } + + private void setProgressMonitorPart(ProgressMonitorPart part) { + fProgressMonitorPart = part; + } + + private ProgressMonitorPart getProgressMonitorPart() { + return fProgressMonitorPart; + } + + private void setProgressMonitorCancelButton(Button button) { + fProgressMonitorCancelButton = button; + } + + private Button getProgressMonitorCancelButton() { + return fProgressMonitorCancelButton; + } + + /** + * Calculate & return a 2 element integer array that specifies the relative + * weights of the selection area and the edit area, based on the specified + * increase in width of the owning shell. The point of this method is calculate + * sash weights such that when the shell gets wider, all of the increase in width + * is given to the edit area (tab folder), and the selection area (tree) stays + * the same width. + */ + private int[] calculateNewSashWeights(int widthIncrease) { + int[] newWeights = new int[2]; + newWeights[0] = getSelectionArea().getBounds().width; + newWeights[1] = getEditArea().getBounds().width + widthIncrease; + return newWeights; + } + + /** + * 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. + */ + private void setShellSize(int width, int height) { + Rectangle bounds = getShell().getDisplay().getBounds(); + getShell().setSize(Math.min(width, bounds.width), Math.min(height, bounds.height)); + } + + /** + * @see ILaunchConfigurationDialog#getMode() + */ + public String getMode() { + return getLaunchGroup().getMode(); + } + + /** + * Returns the current tab group + * + * @return the current tab group, or <code>null</code> if none + */ + public ILaunchConfigurationTabGroup getTabGroup() { + return fTabViewer.getTabGroup(); + } + + /** + * @see ILaunchConfigurationDialog#getTabs() + */ + public ILaunchConfigurationTab[] getTabs() { + if (getTabGroup() == null) { + return null; + } else { + return getTabGroup().getTabs(); + } + } + + /** + * Return whether the current configuration can be discarded. This involves determining + * if it is dirty, and if it is, asking the user what to do. + */ + private boolean canDiscardCurrentConfig() { + if (fTabViewer.isDirty()) { + return showUnsavedChangesDialog(); + } else { + return true; + } + } + + /** + * 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. + */ + private boolean showUnsavedChangesDialog() { + if (fTabViewer.canSave()) { + return showSaveChangesDialog(); + } else { + return showDiscardChangesDialog(); + } + } + + /** + * Create and return a dialog that asks the user whether they want to save + * unsaved changes. Return <code>true </code> if they chose to save changes, + * <code>false</code> otherwise. + */ + private boolean showSaveChangesDialog() { + StringBuffer buffer = new StringBuffer(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.The_configuration___29")); //$NON-NLS-1$ + buffer.append(fTabViewer.getWorkingCopy().getName()); + buffer.append(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.__has_unsaved_changes.__Do_you_wish_to_save_them__30")); //$NON-NLS-1$ + MessageDialog dialog = new MessageDialog(getShell(), + LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Save_changes__31"), //$NON-NLS-1$ + null, + buffer.toString(), + MessageDialog.QUESTION, + new String[] {LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Yes_32"), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.No_33"), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Cancel_34")}, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + 0); + // If user clicked 'Cancel' or closed dialog, return false + int selectedButton = dialog.open(); + if ((selectedButton < 0) || (selectedButton == 2)) { + return false; + } + + // If they hit 'Yes', save the working copy + if (selectedButton == 0) { + fTabViewer.handleApplyPressed(); + } else { + // this will discard the changes + fTabViewer.inputChanged(fTabViewer.getInput()); + } + + return true; + } + + /** + * Create and return a dialog that asks the user whether they want to discard + * unsaved changes. Return <code>true</code> if they chose to discard changes, + * <code>false</code> otherwise. + */ + private boolean showDiscardChangesDialog() { + StringBuffer buffer = new StringBuffer(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.The_configuration___35")); //$NON-NLS-1$ + buffer.append(fTabViewer.getWorkingCopy().getName()); + buffer.append(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.__has_unsaved_changes_that_CANNOT_be_saved_because_of_the_following_error_36")); //$NON-NLS-1$ + buffer.append(fTabViewer.getErrorMesssage()); + buffer.append(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Do_you_wish_to_discard_changes_37")); //$NON-NLS-1$ + MessageDialog dialog = new MessageDialog(getShell(), + LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Discard_changes__38"), //$NON-NLS-1$ + null, + buffer.toString(), + MessageDialog.QUESTION, + new String[] {LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Yes_32"), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.No_33")}, //$NON-NLS-1$ //$NON-NLS-2$ + 1); + // If user clicked 'Yes', return true + int selectedButton = dialog.open(); + if (selectedButton == 0) { + return true; + } + return false; + } + + /** + * Notification the 'Close' button has been pressed. + */ + protected void handleClosePressed() { + if (canDiscardCurrentConfig()) { + fTabViewer.dispose(); + cancelPressed(); + } + } + + /** + * Notification the 'launch' button has been pressed. + * Save and launch. + */ + protected void handleLaunchPressed() { + int result = CANCEL; + ILaunchConfiguration config = fTabViewer.getOriginal(); + try { + if (fTabViewer.isDirty()) { + fTabViewer.handleApplyPressed(); + } + result = doLaunch(config); + } catch (CoreException e) { + DebugUIPlugin.errorDialog(getShell(), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Launch_Configuration_Error_6"), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Exception_occurred_while_launching_configuration._See_log_for_more_information_49"), e); //$NON-NLS-1$ //$NON-NLS-2$ + return; + } + if (result == OK) { + try { + getPreferenceStore().setValue(IDebugPreferenceConstants.PREF_LAST_LAUNCH_CONFIGURATION_SELECTION, config.getMemento()); + } catch (CoreException e) { + DebugUIPlugin.log(e); + } + close(); + } else { + getShell().setFocus(); + updateButtons(); + } + } + + /** + * Save the working copy if necessary, then launch the underlying configuration. + * + * @return one of CANCEL or OK + */ + private int doLaunch(ILaunchConfiguration config) throws CoreException { + + if (!DebugUITools.saveAndBuildBeforeLaunch()) { + return CANCEL; + } + + // liftoff + ILaunch launch = launchWithProgress(config); + + // If the launch was cancelled, get out. Otherwise, notify the tabs of the successful launch. + if (cancelButtonPressed()) { + launch.terminate(); + return CANCEL; + } else if (launch != null) { + ILaunchConfigurationTabGroup group = getTabGroup(); + if (group != null) { + group.launched(launch); + } + } + + return OK; + } + + /** + * @return the resulting launch, or <code>null</code> if cancelled. + * @exception CoreException if an exception occurrs launching + */ + private ILaunch launchWithProgress(final ILaunchConfiguration config) throws CoreException { + final ILaunch[] launchResult = new ILaunch[1]; + // Do the launch + IRunnableWithProgress runnable = new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) throws InvocationTargetException { + try { + launchResult[0] = config.launch(getMode(), monitor); + } catch (CoreException e) { + throw new InvocationTargetException(e); + } + } + }; + try { + run(true, true, runnable); + } catch (InterruptedException e) { + return null; + } catch (InvocationTargetException e) { + Throwable t = e.getTargetException(); + if (t instanceof CoreException) { + throw (CoreException)t; + } else { + IStatus status = new Status(IStatus.ERROR, IDebugUIConstants.PLUGIN_ID, DebugException.INTERNAL_ERROR, LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Exception_occurred_while_launching_50"), t); //$NON-NLS-1$ + throw new CoreException(status); + } + } finally { + //remove any "error" launch + ILaunchManager manager= DebugPlugin.getDefault().getLaunchManager(); + ILaunch[] launches= manager.getLaunches(); + for (int i = 0; i < launches.length; i++) { + ILaunch iLaunch = launches[i]; + if (!iLaunch.hasChildren()) { + manager.removeLaunch(iLaunch); + } + } + } + + return launchResult[0]; + } + + private IPreferenceStore getPreferenceStore() { + return DebugUIPlugin.getDefault().getPreferenceStore(); + } + + /*************************************************************************************** + * + * ProgressMonitor & IRunnableContext related methods + * + ***************************************************************************************/ + + /** + * @see IRunnableContext#run(boolean, boolean, IRunnableWithProgress) + */ + public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException { + if (isVisible()) { + // The operation can only be canceled if it is executed in a separate thread. + // Otherwise the UI is blocked anyway. + Object state = aboutToStart(); + fActiveRunningOperations++; + try { + ModalContext.run(runnable, fork, fProgressMonitorPart, getShell().getDisplay()); + } finally { + fActiveRunningOperations--; + stopped(state); + } + } else { + ProgressMonitorDialog dialog = new ProgressMonitorDialog(DebugUIPlugin.getShell()); + dialog.run(fork, cancelable, runnable); + } + } + + /** + * About to start a long running operation triggered through + * the dialog. Shows the progress monitor and disables the dialog's + * buttons and controls. + * + * @return the saved UI state + */ + private Object aboutToStart() { + Map savedState = null; + if (getShell() != null) { + // Save focus control + Control focusControl = getShell().getDisplay().getFocusControl(); + if (focusControl != null && focusControl.getShell() != getShell()) { + focusControl = null; + } + + // Set the busy cursor to all shells. + Display d = getShell().getDisplay(); + waitCursor = new Cursor(d, SWT.CURSOR_WAIT); + setDisplayCursor(waitCursor); + + // Set the arrow cursor to the cancel component. + arrowCursor= new Cursor(d, SWT.CURSOR_ARROW); + getProgressMonitorCancelButton().setCursor(arrowCursor); + + // Deactivate shell + savedState = saveUIState(); + if (focusControl != null) { + savedState.put(FOCUS_CONTROL, focusControl); + } + + // Attach the progress monitor part to the cancel button + getProgressMonitorCancelButton().setEnabled(true); + setCancelButtonPressed(false); + getProgressMonitorPart().attachToCancelComponent(getProgressMonitorCancelButton()); + getProgressMonitorPart().setVisible(true); + getProgressMonitorCancelButton().setFocus(); + } + return savedState; + } + + /** + * A long running operation triggered through the dialog + * was stopped either by user input or by normal end. + * Hides the progress monitor and restores the enable state + * of the dialog's buttons and controls. + * + * @param savedState the saved UI state as returned by <code>aboutToStart</code> + * @see #aboutToStart + */ + private void stopped(Object savedState) { + if (getShell() != null) { + getProgressMonitorPart().setVisible(false); + getProgressMonitorPart().removeFromCancelComponent(getProgressMonitorCancelButton()); + Map state = (Map)savedState; + restoreUIState(state); + + setDisplayCursor(null); + waitCursor.dispose(); + waitCursor = null; + arrowCursor.dispose(); + arrowCursor = null; + Control focusControl = (Control)state.get(FOCUS_CONTROL); + if (focusControl != null) { + focusControl.setFocus(); + } + } + } + + /** + * Captures and returns the enabled/disabled state of the wizard dialog's + * buttons and the tree of controls for the currently showing page. All + * these controls are disabled in the process, with the possible excepton of + * the Cancel button. + * + * @return a map containing the saved state suitable for restoring later + * with <code>restoreUIState</code> + * @see #restoreUIState + */ + private Map saveUIState() { + Map savedState= new HashMap(10); + saveEnableStateAndSet(getButtonActionNew().getButton(), savedState, "new", false);//$NON-NLS-1$ + saveEnableStateAndSet(getButtonActionDelete().getButton(), savedState, "delete", false);//$NON-NLS-1$ + saveEnableStateAndSet(getButton(ID_LAUNCH_BUTTON), savedState, "launch", false);//$NON-NLS-1$ + saveEnableStateAndSet(getButton(ID_CLOSE_BUTTON), savedState, "close", false);//$NON-NLS-1$ + savedState.put("editarea", ControlEnableState.disable(getEditArea()));//$NON-NLS-1$ + return savedState; + } + + /** + * Saves the enabled/disabled state of the given control in the + * given map, which must be modifiable. + * + * @param w the control, or <code>null</code> if none + * @param h the map (key type: <code>String</code>, element type: + * <code>Boolean</code>) + * @param key the key + * @param enabled <code>true</code> to enable the control, + * and <code>false</code> to disable it + * @see #restoreEnableStateAndSet + */ + private void saveEnableStateAndSet(Control w, Map h, String key, boolean enabled) { + if (w != null) { + h.put(key, new Boolean(w.isEnabled())); + w.setEnabled(enabled); + } + } + + /** + * Restores the enabled/disabled state of the wizard dialog's + * buttons and the tree of controls for the currently showing page. + * + * @param state a map containing the saved state as returned by + * <code>saveUIState</code> + * @see #saveUIState + */ + private void restoreUIState(Map state) { + restoreEnableState(getButtonActionNew().getButton(), state, "new");//$NON-NLS-1$ + restoreEnableState(getButtonActionDelete().getButton(), state, "delete");//$NON-NLS-1$ + restoreEnableState(getButton(ID_LAUNCH_BUTTON), state, "launch");//$NON-NLS-1$ + restoreEnableState(getButton(ID_CLOSE_BUTTON), state, "close");//$NON-NLS-1$ + ControlEnableState tabState = (ControlEnableState) state.get("editarea");//$NON-NLS-1$ + tabState.restore(); + } + + /** + * Restores the enabled/disabled state of the given control. + * + * @param w the control + * @param h the map (key type: <code>String</code>, element type: + * <code>Boolean</code>) + * @param key the key + * @see #saveEnableStateAndSet + */ + private void restoreEnableState(Control w, Map h, String key) { + if (w != null) { + Boolean b = (Boolean) h.get(key); + if (b != null) + w.setEnabled(b.booleanValue()); + } + } + + private void setCancelButtonPressed(boolean pressed) { + fCancelButtonPressed = pressed; + } + + private boolean cancelButtonPressed() { + return fCancelButtonPressed; + } + + /** + * Sets the given cursor for all shells currently active + * for this window's display. + * + * @param cursor the cursor + */ + private void setDisplayCursor(Cursor cursor) { + Shell[] shells = getShell().getDisplay().getShells(); + for (int i = 0; i < shells.length; i++) + shells[i].setCursor(cursor); + } + + /** + * @see ILaunchConfigurationDialog#updateButtons() + */ + public void updateButtons() { + if (isInitializingTabs()) { + return; + } + + // New & Delete buttons + getButtonActionNew().setEnabled(getNewAction().isEnabled()); + getButtonActionDelete().setEnabled(getDeleteAction().isEnabled()); + + // Launch button + getButton(ID_LAUNCH_BUTTON).setEnabled(fTabViewer.canLaunch()); + + fTabViewer.refresh(); + } + + /** + * @see ILaunchConfigurationDialog#getActiveTab() + */ + public ILaunchConfigurationTab getActiveTab() { + return fTabViewer.getActiveTab(); + } + + /** + * @see ILaunchConfigurationDialog#updateMessage() + */ + public void updateMessage() { + if (isInitializingTabs()) { + return; + } + setErrorMessage(fTabViewer.getErrorMesssage()); + setMessage(fTabViewer.getMesssage()); + } + + /** + * Show the default informational message that explains how to create a new configuration. + */ + private void setDefaultMessage() { + setMessage(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Select_a_type_of_configuration_to_create,_and_press___new__51")); //$NON-NLS-1$ + } + + /** + * Set the tooltip of the config tree label based on the current working set in effect. + */ + private void updateTreeLabelTooltip() { + LaunchConfigurationWorkingSetActionManager mgr = getWorkingSetActionManager(); + if (mgr != null) { + IWorkingSet workingSet = mgr.getWorkingSet(); + if (workingSet != null) { + String newTooltip = MessageFormat.format(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Working_Set__{0}_1"), new String[] {workingSet.getName()} ); //$NON-NLS-1$ + getTreeLabel().setToolTipText(newTooltip); + return; + } + } + + // No working set, so don't show a tooltip + getTreeLabel().setToolTipText(null); + } + + /** + * Returns the working set action manager + */ + private LaunchConfigurationWorkingSetActionManager getWorkingSetActionManager() { + return fLaunchConfigurationView.getWorkingSetActionManager(); + } + + /** + * Returns the launch configuration selection area control. + * + * @return control + */ + private Composite getSelectionArea() { + return fSelectionArea; + } + + /** + * Sets the launch configuration selection area control. + * + * @param editArea control + */ + private void setSelectionArea(Composite selectionArea) { + fSelectionArea = selectionArea; + } + + /** + * Returns the launch configuration edit area control. + * + * @return control + */ + private Composite getEditArea() { + return fEditArea; + } + + /** + * Sets the launch configuration edit area control. + * + * @param editArea control + */ + private void setEditArea(Composite editArea) { + fEditArea = editArea; + } + + /** + * @see ILaunchConfigurationDialog#setName(String) + */ + public void setName(String name) { + fTabViewer.setName(name); + } + + /** + * @see ILaunchConfigurationDialog#generateName(String) + */ + public String generateName(String name) { + if (name == null) { + name = ""; //$NON-NLS-1$ + } + return getLaunchManager().generateUniqueLaunchConfigurationNameFrom(name); + } + + /** + * Returns the initial launch configuration type, or <code>null</code> if none has been set. + */ + private ILaunchConfigurationType getInitialConfigType() { + return fInitialConfigType; + } + + /** + * Sets the initial launch configuration type to be used when this dialog is opened. + */ + public void setInitialConfigType(ILaunchConfigurationType configType) { + fInitialConfigType = configType; + } + + /** + * Returns the initial selection shown in this dialog when opened in + * <code>LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_SELECTION</code> mode. + */ + private IStructuredSelection getInitialSelection() { + return fInitialSelection; + } + + /** + * 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; + } + + /** + * Handles key events in the tree viewer. Specifically + * when the delete key is pressed. + */ + protected void handleTreeViewerKeyPressed(KeyEvent event) { + if (event.character == SWT.DEL && event.stateMask == 0) { + if (getButtonActionDelete().isEnabled()) { + getButtonActionDelete().run(); + } + } + } + + private void setButtonActionNew(ButtonAction action) { + fButtonActionNew = action; + } + + private ButtonAction getButtonActionNew() { + return fButtonActionNew; + } + + private void setButtonActionDelete(ButtonAction action) { + fButtonActionDelete = action; + } + + private ButtonAction getButtonActionDelete() { + return fButtonActionDelete; + } + + private void setTreeLabel(Label treeLabel) { + fTreeLabel = treeLabel; + } + + private Label getTreeLabel() { + return fTreeLabel; + } + + public static void setCurrentlyVisibleLaunchConfigurationDialog(ILaunchConfigurationDialog dialog) { + fgCurrentlyVisibleLaunchConfigurationDialog = dialog; + } + + public static ILaunchConfigurationDialog getCurrentlyVisibleLaunchConfigurationDialog() { + return fgCurrentlyVisibleLaunchConfigurationDialog; + } + + /** + * Extension of <code>Action</code> that manages a <code>Button</code> + * widget. This allows common handling for actions that must appear in + * a pop-up menu and also as a (non-toolbar) button in the UI. + */ + private abstract class ButtonAction extends Action { + + protected Button fButton; + + /** + * Construct a ButtonAction handler. All details of the specified + * <code>Button</code>'s layout and appearance should be handled + * external to this class. + */ + public ButtonAction(String text, Button button) { + super(text); + fButton = button; + if (fButton != null) { + fButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent evt) { + ButtonAction.this.run(); + } + }); + } + } + + public Button getButton() { + return fButton; + } + + /** + * @see IAction#setEnabled(boolean) + */ + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + if (fButton != null) { + fButton.setEnabled(enabled); + } + } + } + + /** + * Handler for creating a new configuration. + */ + private class ButtonActionNew extends ButtonAction { + + public ButtonActionNew(String text, Button button) { + super(text, button); + } + + public void run() { + getNewAction().run(); + } + } + + /** + * Handler for deleting a configuration. + */ + private class ButtonActionDelete extends ButtonAction { + + public ButtonActionDelete(String text, Button button) { + super(text, button); + } + + public void run() { + getDeleteAction().run(); + } + } + + private class DoubleClickAction extends Action { + /** + * @see org.eclipse.jface.action.IAction#run() + */ + public void run() { + IStructuredSelection selection = (IStructuredSelection)fLaunchConfigurationView.getViewer().getSelection(); + Object target = selection.getFirstElement(); + if (target instanceof ILaunchConfiguration) { + handleLaunchPressed(); + } else { + getNewAction().run(); + } + } + + } + + /** + * 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; + } + + /** + * Sets the launch group to display. + * + * @param group launch group + */ + protected void setLaunchGroup(LaunchGroupExtension group) { + fGroup = group; + } + + /** + * Returns the launch group being displayed. + * + * @return launch group
*/ + public LaunchGroupExtension getLaunchGroup() { + return fGroup; + } + + protected AbstractLaunchConfigurationAction getNewAction() { + return (AbstractLaunchConfigurationAction)fLaunchConfigurationView.getAction(CreateLaunchConfigurationAction.ID_CREATE_ACTION); + } + + protected AbstractLaunchConfigurationAction getDeleteAction() { + return (AbstractLaunchConfigurationAction)fLaunchConfigurationView.getAction(DeleteLaunchConfigurationAction.ID_DELETE_ACTION); + } + + protected AbstractLaunchConfigurationAction getDuplicateAction() { + return (AbstractLaunchConfigurationAction)fLaunchConfigurationView.getAction(DuplicateLaunchConfigurationAction.ID_DUPLICATE_ACTION); + } + +}
\ No newline at end of file |