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 | |
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
17 files changed, 3404 insertions, 100 deletions
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/IDebugHelpContextIds.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/IDebugHelpContextIds.java index 354e02925..f95d14ad9 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/IDebugHelpContextIds.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/IDebugHelpContextIds.java @@ -38,6 +38,7 @@ public interface IDebugHelpContextIds { public static final String BREAKPOINT_VIEW = PREFIX + "breakpoint_view_context"; //$NON-NLS-1$ public static final String CONSOLE_VIEW = PREFIX + "console_view_context"; //$NON-NLS-1$ public static final String EXPRESSION_VIEW = PREFIX + "expression_view_context"; //$NON-NLS-1$ + public static final String LAUNCH_CONFIGURATION_VIEW = PREFIX + "launch_configuration_view_context"; //$NON-NLS-1$ // Preference pages public static final String DEBUG_PREFERENCE_PAGE = PREFIX + "debug_preference_page_context"; //$NON-NLS-1$ diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ExecutionAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ExecutionAction.java index b7db3d2c1..b44e2fbc2 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ExecutionAction.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ExecutionAction.java @@ -6,14 +6,8 @@ package org.eclipse.debug.internal.ui.actions; */ import org.eclipse.debug.internal.ui.DebugUIPlugin; -import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationDialog; -import org - .eclipse - .debug - .internal - .ui - .launchConfigurations - .LaunchConfigurationManager; +import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationManager; +import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsDialog; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.swt.widgets.Event; @@ -41,8 +35,8 @@ public abstract class ExecutionAction implements IActionDelegateWithEvent { return; } IStructuredSelection selection= DebugUIPlugin.resolveSelection(dwindow); - LaunchConfigurationDialog dialog = new LaunchConfigurationDialog(DebugUIPlugin.getShell(), selection, LaunchConfigurationManager.getDefault().getDefaultLanuchGroup(getMode())); - dialog.setOpenMode(LaunchConfigurationDialog.LAUNCH_CONFIGURATION_DIALOG_LAUNCH_LAST); + LaunchConfigurationsDialog dialog = new LaunchConfigurationsDialog(DebugUIPlugin.getShell(), selection, LaunchConfigurationManager.getDefault().getDefaultLanuchGroup(getMode())); + dialog.setOpenMode(LaunchConfigurationsDialog.LAUNCH_CONFIGURATION_DIALOG_LAUNCH_LAST); dialog.open(); } diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/OpenDebugConfigurations.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/OpenDebugConfigurations.java index 2ea872e4a..dfc4514ae 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/OpenDebugConfigurations.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/OpenDebugConfigurations.java @@ -1,6 +1,5 @@ package org.eclipse.debug.internal.ui.actions; -import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchManager; /* @@ -16,10 +15,6 @@ public class OpenDebugConfigurations extends OpenLaunchConfigurationsAction { public OpenDebugConfigurations() { super(); } - - public OpenDebugConfigurations(ILaunchConfigurationType configType) { - super(configType); - } /** * @see OpenLaunchConfigurationsAction#getMode() diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/OpenLaunchConfigurationsAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/OpenLaunchConfigurationsAction.java index 552b89fad..fdc662db5 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/OpenLaunchConfigurationsAction.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/OpenLaunchConfigurationsAction.java @@ -9,14 +9,8 @@ import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.internal.ui.DebugPluginImages; import org.eclipse.debug.internal.ui.DebugUIPlugin; -import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationDialog; -import org - .eclipse - .debug - .internal - .ui - .launchConfigurations - .LaunchConfigurationManager; +import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationManager; +import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsDialog; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; @@ -28,14 +22,11 @@ import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; /** - * Abstract action for opening the launch configuration dialog in run or debug mode. - * This class is used in two ways: to simply open the dialog, and to open the dialog and - * create a new configuration of a specified type. + * Abstract action for opening the launch configuration dialog in run or debug + * mode. */ public abstract class OpenLaunchConfigurationsAction extends Action implements IWorkbenchWindowActionDelegate { - private boolean fCreateNewConfigMode; - /** * The launch configuration type this action will cause to be created in the launch * configuration dialog. @@ -49,7 +40,6 @@ public abstract class OpenLaunchConfigurationsAction extends Action implements I public OpenLaunchConfigurationsAction() { super(); - fCreateNewConfigMode = false; setConfigType(null); ImageDescriptor imageDescriptor = null; if (getMode() == ILaunchManager.DEBUG_MODE) { @@ -60,28 +50,6 @@ public abstract class OpenLaunchConfigurationsAction extends Action implements I setText(getLabelText()); setImageDescriptor(imageDescriptor); } - - /** - * Initialize this action from the specified <code>ILaunchConfigurationType</code>. - */ - protected OpenLaunchConfigurationsAction(ILaunchConfigurationType configType) { - fCreateNewConfigMode = true; - setConfigType(configType); - setText(configType.getName()); - - ImageDescriptor descriptor = DebugPluginImages.getImageDescriptor(configType.getIdentifier()); - if (descriptor == null) { - if (getMode().equals(ILaunchManager.DEBUG_MODE)) { - descriptor= DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_ACT_DEBUG); - } else { - descriptor= DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_ACT_RUN); - } - } - - if (descriptor != null) { - setImageDescriptor(descriptor); - } - } /** * @see IWorkbenchWindowActionDelegate#init(IWorkbenchWindow) @@ -129,13 +97,8 @@ public abstract class OpenLaunchConfigurationsAction extends Action implements I } else { ss = new StructuredSelection(); } - LaunchConfigurationDialog dialog = new LaunchConfigurationDialog(window.getShell(), ss, LaunchConfigurationManager.getDefault().getDefaultLanuchGroup(getMode())); - if (fCreateNewConfigMode) { - dialog.setOpenMode(LaunchConfigurationDialog.LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_NEW_CONFIG_OF_TYPE); - dialog.setInitialConfigType(getConfigType()); - } else { - dialog.setOpenMode(LaunchConfigurationDialog.LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_LAST_LAUNCHED); - } + LaunchConfigurationsDialog dialog = new LaunchConfigurationsDialog(window.getShell(), ss, LaunchConfigurationManager.getDefault().getDefaultLanuchGroup(getMode())); + dialog.setOpenMode(LaunchConfigurationsDialog.LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_LAST_LAUNCHED); dialog.open(); } } diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/OpenRunConfigurations.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/OpenRunConfigurations.java index 97023dbdb..d692a883b 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/OpenRunConfigurations.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/OpenRunConfigurations.java @@ -1,6 +1,5 @@ package org.eclipse.debug.internal.ui.actions; -import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchManager; /* @@ -17,10 +16,6 @@ public class OpenRunConfigurations extends OpenLaunchConfigurationsAction { super(); } - public OpenRunConfigurations(ILaunchConfigurationType configType) { - super(configType); - } - /** * @see OpenLaunchConfigurationsAction#getMode() */ diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/RelaunchLastAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/RelaunchLastAction.java index a300b9560..125d639b0 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/RelaunchLastAction.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/RelaunchLastAction.java @@ -10,20 +10,8 @@ import java.text.MessageFormat; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.internal.ui.DebugUIPlugin; -import org - .eclipse - .debug - .internal - .ui - .launchConfigurations - .LaunchConfigurationDialog; -import org - .eclipse - .debug - .internal - .ui - .launchConfigurations - .LaunchConfigurationManager; +import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationManager; +import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsDialog; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.MessageDialog; @@ -86,8 +74,8 @@ public abstract class RelaunchLastAction implements IWorkbenchWindowActionDelega return; } IStructuredSelection selection= DebugUIPlugin.resolveSelection(dwindow); - LaunchConfigurationDialog dialog = new LaunchConfigurationDialog(DebugUIPlugin.getShell(), selection, LaunchConfigurationManager.getDefault().getDefaultLanuchGroup(getMode())); - dialog.setOpenMode(LaunchConfigurationDialog.LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_LAST_LAUNCHED); + LaunchConfigurationsDialog dialog = new LaunchConfigurationsDialog(DebugUIPlugin.getShell(), selection, LaunchConfigurationManager.getDefault().getDefaultLanuchGroup(getMode())); + dialog.setOpenMode(LaunchConfigurationsDialog.LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_LAST_LAUNCHED); dialog.open(); } diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/AbstractLaunchConfigurationAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/AbstractLaunchConfigurationAction.java new file mode 100644 index 000000000..cb320c9a6 --- /dev/null +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/AbstractLaunchConfigurationAction.java @@ -0,0 +1,115 @@ +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 org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.actions.SelectionListenerAction; + +/** + * Common function/behavior for launch configuration view actions + */ +public abstract class AbstractLaunchConfigurationAction extends SelectionListenerAction { + + /** + * Allows a requestor to abort this action. + */ + public interface IConfirmationRequestor { + /** + * Returns whether this action should proceed. Confirmation is requested + * when an action is run. + * + * @return whether this action should proceed + */ + public boolean getConfirmation(); + } + + /** + * This action's confirmation requestor or <code>null</code> if none + */ + private IConfirmationRequestor fConfirmationRequestor; + + /** + * The viewer this action is working on + */ + private Viewer fViewer; + + /** + * Constructor for AbstractLaunchConfigurationAction. + * @param text + */ + public AbstractLaunchConfigurationAction(String text, Viewer viewer) { + super(text); + fViewer = viewer; + fViewer.addSelectionChangedListener(this); + } + + /** + * Returns the shell this action is contained in. + * + * @return the shell this action is contained in + */ + protected Shell getShell() { + return getViewer().getControl().getShell(); + } + + /** + * Returns the viewer this action is working on + * + * @return the viewer this action is working on + */ + protected Viewer getViewer() { + return fViewer; + } + + /** + * Performs this action once confirmation has been aquired. Subclasses + * should override this method. + */ + protected abstract void performAction(); + + /** + * @see org.eclipse.jface.action.IAction#run() + */ + public final void run() { + if (fConfirmationRequestor != null) { + if (!fConfirmationRequestor.getConfirmation()) { + return; + } + } + performAction(); + } + + /** + * Sets this action's confirmation requestor. + * + * @param confirmationRequestor + */ + public void setConfirmationRequestor(IConfirmationRequestor confirmationRequestor) { + fConfirmationRequestor = confirmationRequestor; + } + + /** + * Disposes this action + */ + public void dispose() { + fViewer.removeSelectionChangedListener(this); + } + + /** + * Show an error dialog on the given exception. + * + * @param exception + */ + protected void errorDialog(CoreException exception) { + ErrorDialog.openError(getShell(), null, null, exception.getStatus()); + } + +} diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/CreateLaunchConfigurationAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/CreateLaunchConfigurationAction.java new file mode 100644 index 000000000..85f657fb5 --- /dev/null +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/CreateLaunchConfigurationAction.java @@ -0,0 +1,85 @@ +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 org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationType; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.debug.ui.ILaunchConfigurationDialog; +import org.eclipse.debug.ui.ILaunchConfigurationTab; +import org.eclipse.debug.ui.ILaunchConfigurationTabGroup; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.Viewer; + +/** + * Creates a new launch configuration based on the selection. + */ +public class CreateLaunchConfigurationAction extends AbstractLaunchConfigurationAction { + + /** + * Action identifier for IDebugView#getAction(String) + */ + public static final String ID_CREATE_ACTION = DebugUIPlugin.getUniqueIdentifier() + ".ID_CREATE_ACTION"; + + /** + * Constructs an action to create a launch configuration + */ + public CreateLaunchConfigurationAction(Viewer viewer) { + super("Ne&w", viewer); + } + + /** + * @see AbstractLaunchConfigurationAction#performAction() + */ + protected void performAction() { + Object object = getStructuredSelection().getFirstElement(); + ILaunchConfigurationType type= null; + // Construct a new config of the selected type + if (object instanceof ILaunchConfiguration) { + ILaunchConfiguration config= (ILaunchConfiguration) object; + try { + type = config.getType(); + } catch (CoreException e) { + errorDialog(e); + return; + } + } else { + type = (ILaunchConfigurationType) object; + } + + try { + ILaunchConfigurationWorkingCopy wc = type.newInstance(null, DebugPlugin.getDefault().getLaunchManager().generateUniqueLaunchConfigurationNameFrom("New_configuration")); + ILaunchConfigurationTabGroup tabGroup = LaunchConfigurationPresentationManager.getDefault().getTabGroup(wc.getType()); + // 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++) { + ILaunchConfigurationTab tab = tabs[i]; + tab.setLaunchConfigurationDialog(dialog); + } + tabGroup.setDefaults(wc); + tabGroup.dispose(); + wc.doSave(); + } catch (CoreException e) { + errorDialog(e); + return; + } + } + + /** + * @see org.eclipse.ui.actions.SelectionListenerAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection) + */ + protected boolean updateSelection(IStructuredSelection selection) { + return selection.size() == 1; + } + +} diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/DeleteLaunchConfigurationAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/DeleteLaunchConfigurationAction.java new file mode 100644 index 000000000..479eb9f58 --- /dev/null +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/DeleteLaunchConfigurationAction.java @@ -0,0 +1,78 @@ +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.util.Iterator; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.Viewer; + +/** + * Deletes the selected launch configuration(s). + */ +public class DeleteLaunchConfigurationAction extends AbstractLaunchConfigurationAction { + + /** + * Action identifier for IDebugView#getAction(String) + */ + public static final String ID_DELETE_ACTION = DebugUIPlugin.getUniqueIdentifier() + ".ID_DELETE_ACTION"; + + /** + * Constructs an action to delete launch configuration(s) + */ + public DeleteLaunchConfigurationAction(Viewer viewer) { + super("Dele&te", viewer); + } + + /** + * @see AbstractLaunchConfigurationAction#performAction() + */ + protected void performAction() { + IStructuredSelection selection = getStructuredSelection(); + + // Make the user confirm the deletion + String dialogMessage = selection.size() > 1 ? LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Do_you_wish_to_delete_the_selected_launch_configurations__1") : LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Do_you_wish_to_delete_the_selected_launch_configuration__2"); //$NON-NLS-1$ //$NON-NLS-2$ + boolean ok = MessageDialog.openQuestion(getShell(), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Confirm_Launch_Configuration_Deletion_3"), dialogMessage); //$NON-NLS-1$ + if (!ok) { + return; + } + + getViewer().getControl().setRedraw(false); + Iterator iterator = selection.iterator(); + while (iterator.hasNext()) { + ILaunchConfiguration configuration = (ILaunchConfiguration)iterator.next(); + try { + configuration.delete(); + } catch (CoreException e) { + errorDialog(e); + } + } + getViewer().getControl().setRedraw(true); + } + + /** + * @see org.eclipse.ui.actions.SelectionListenerAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection) + */ + protected boolean updateSelection(IStructuredSelection selection) { + if (selection.isEmpty()) { + return false; + } + Iterator items = selection.iterator(); + while (items.hasNext()) { + if (!(items.next() instanceof ILaunchConfiguration)) { + return false; + } + } + return true; + } + +} diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/DuplicateLaunchConfigurationAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/DuplicateLaunchConfigurationAction.java new file mode 100644 index 000000000..a3512ac95 --- /dev/null +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/DuplicateLaunchConfigurationAction.java @@ -0,0 +1,56 @@ +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 org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.Viewer; + +/** + * Duplicates the selected launch configuration. + */ +public class DuplicateLaunchConfigurationAction extends AbstractLaunchConfigurationAction { + + /** + * Action identifier for IDebugView#getAction(String) + */ + public static final String ID_DUPLICATE_ACTION = DebugUIPlugin.getUniqueIdentifier() + ".ID_DUPLICATE_ACTION"; + + /** + * Constructs an action to duplicate a launch configuration + */ + public DuplicateLaunchConfigurationAction(Viewer viewer) { + super("&Duplicate", viewer); + } + + /** + * @see AbstractLaunchConfigurationAction#performAction() + */ + protected void performAction() { + ILaunchConfiguration original = (ILaunchConfiguration)getStructuredSelection().getFirstElement(); + String newName = DebugPlugin.getDefault().getLaunchManager().generateUniqueLaunchConfigurationNameFrom(original.getName()); + try { + ILaunchConfigurationWorkingCopy newWorkingCopy = original.copy(newName); + newWorkingCopy.doSave(); + } catch (CoreException e) { + errorDialog(e); + } + } + + /** + * @see org.eclipse.ui.actions.SelectionListenerAction#updateSelection(org.eclipse.jface.viewers.IStructuredSelection) + */ + protected boolean updateSelection(IStructuredSelection selection) { + return selection.size() == 1 && selection.getFirstElement() instanceof ILaunchConfiguration; + } + +} diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationDialog.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationDialog.java index 8796919e3..2fa842b4b 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationDialog.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationDialog.java @@ -99,6 +99,8 @@ import org.eclipse.ui.model.WorkbenchViewerSorter; /** * The dialog used to edit and launch launch configurations. + * + * @deprecated use LaunchConfigurationsDialog instead */ public class LaunchConfigurationDialog extends TitleAreaDialog implements ISelectionChangedListener, diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationTabGroupViewer.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationTabGroupViewer.java new file mode 100644 index 000000000..ebcfeff82 --- /dev/null +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationTabGroupViewer.java @@ -0,0 +1,1024 @@ +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.text.MessageFormat; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationType; +import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; +import org.eclipse.debug.core.ILaunchManager; +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.debug.internal.ui.SWTUtil; +import org.eclipse.debug.ui.ILaunchConfigurationDialog; +import org.eclipse.debug.ui.ILaunchConfigurationTab; +import org.eclipse.debug.ui.ILaunchConfigurationTabGroup; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.TabFolder; +import org.eclipse.swt.widgets.TabItem; +import org.eclipse.swt.widgets.Text; + +/** + * A viewer that displays tabs for a launch configuration, with apply and revert + * buttons. + */ +public class LaunchConfigurationTabGroupViewer extends Viewer { + + /** + * Containing launch dialog + */ + private ILaunchConfigurationDialog fDialog; + + /** + * The this viewer's input + */ + private Object fInput; + + /** + * The launch configuration (original) being edited + */ + private ILaunchConfiguration fOriginal; + + /** + * The working copy of the original + */ + private ILaunchConfigurationWorkingCopy fWorkingCopy; + + /** + * This view's control, which contains a composite area of controls + */ + private Composite fViewerControl; + + /** + * Composite area containing all this viewer's controls, which can be + * hidden/shown. + */ + private Composite fViewerArea; + + /** + * Name text widget + */ + private Text fNameWidget; + + /** + * Composite containing the launch config tab widgets + */ + private Composite fTabComposite; + + /** + * Tab folder + */ + private TabFolder fTabFolder; + + /** + * The current tab group being displayed + */ + private ILaunchConfigurationTabGroup fTabGroup; + + /** + * The type of config tabs are currently displayed + * for + */ + private ILaunchConfigurationType fTabType; + + /** + * Index of the active tab + */ + private int fCurrentTabIndex = -1; + + /** + * Apply & Rever buttons + */ + private Button fApplyButton; + private Button fRevertButton; + + /** + * Whether tabs are currently being disposed or initialized + */ + private boolean fDisposingTabs = false; + private boolean fInitializingTabs = false; + + /** + * Constructs a viewer in the given composite, contained by the given + * launch configuration dialog. + * + * @param parent composite containing this viewer + * @param dialog containing launch configuration dialog + */ + public LaunchConfigurationTabGroupViewer(Composite parent, ILaunchConfigurationDialog dialog) { + super(); + fDialog = dialog; + createControl(parent); + } + + public void dispose() { + disposeExistingTabs(); + } + + /** + * Creates this viewer's control This area displays the name of the launch + * configuration currently being edited, as well as a tab folder of tabs + * that are applicable to the launch configuration. + * + * @return the composite used for launch configuration editing + */ + private void createControl(Composite parent) { + fViewerControl = new Composite(parent, SWT.NONE); + GridLayout outerCompLayout = new GridLayout(); + outerCompLayout.numColumns = 1; + outerCompLayout.marginHeight = 0; + outerCompLayout.marginWidth = 0; + fViewerControl.setLayout(outerCompLayout); + + Composite comp = new Composite(fViewerControl, SWT.NONE); + setViewerArea(comp); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + layout.marginHeight = 0; + layout.marginWidth = 5; + comp.setLayout(layout); + GridData gd = new GridData(GridData.FILL_BOTH); + comp.setLayoutData(gd); + + Label nameLabel = new Label(comp, SWT.HORIZONTAL | SWT.LEFT); + nameLabel.setText(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.&Name__16")); //$NON-NLS-1$ + gd = new GridData(GridData.BEGINNING); + nameLabel.setLayoutData(gd); + + Text nameText = new Text(comp, SWT.SINGLE | SWT.BORDER); + gd = new GridData(GridData.FILL_HORIZONTAL); + nameText.setLayoutData(gd); + setNameWidget(nameText); + + getNameWidget().addModifyListener( + new ModifyListener() { + public void modifyText(ModifyEvent e) { + handleNameModified(); + } + } + ); + + Label spacer = new Label(comp, SWT.NONE); + gd = new GridData(); + gd.horizontalSpan = 2; + spacer.setLayoutData(gd); + + fTabComposite = new Composite(comp, SWT.NONE); + GridLayout outerTabCompositeLayout = new GridLayout(); + outerTabCompositeLayout.marginHeight = 0; + outerTabCompositeLayout.marginWidth = 0; + fTabComposite.setLayout(outerTabCompositeLayout); + gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 2; + fTabComposite.setLayoutData(gd); + + TabFolder tabFolder = new TabFolder(fTabComposite, SWT.NONE); + setTabFolder(tabFolder); + gd = new GridData(GridData.FILL_BOTH); + tabFolder.setLayoutData(gd); + getTabFolder().addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + if (!isInitializingTabs()) { + handleTabSelected(); + } + } + }); + + Composite buttonComp = new Composite(comp, SWT.NONE); + GridLayout buttonCompLayout = new GridLayout(); + buttonCompLayout.numColumns = 2; + buttonComp.setLayout(buttonCompLayout); + gd = new GridData(GridData.HORIZONTAL_ALIGN_END); + gd.horizontalSpan = 2; + buttonComp.setLayoutData(gd); + + setApplyButton(new Button(buttonComp, SWT.PUSH)); + getApplyButton().setText(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.&Apply_17")); //$NON-NLS-1$ + gd = new GridData(GridData.HORIZONTAL_ALIGN_END); + getApplyButton().setLayoutData(gd); + SWTUtil.setButtonDimensionHint(getApplyButton()); + getApplyButton().addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent evt) { + handleApplyPressed(); + } + }); + + setRevertButton(new Button(buttonComp, SWT.PUSH)); + getRevertButton().setText(LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Revert_2")); //$NON-NLS-1$ + gd = new GridData(GridData.HORIZONTAL_ALIGN_END); + getRevertButton().setLayoutData(gd); + SWTUtil.setButtonDimensionHint(getRevertButton()); + getRevertButton().addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent evt) { + handleRevertPressed(); + } + }); + + } + + /** + * Sets the apply button + */ + private void setApplyButton(Button button) { + fApplyButton = button; + } + + /** + * Returns the apply button + */ + protected Button getApplyButton() { + return fApplyButton; + } + + /** + * Sets the revert button + */ + private void setRevertButton(Button button) { + fRevertButton = button; + } + + /** + * Returns the revert button + */ + protected Button getRevertButton() { + return fRevertButton; + } + + /** + * Sets the tab folder + */ + private void setTabFolder(TabFolder tabFolder) { + fTabFolder = tabFolder; + } + + /** + * Sets the tab folder + */ + private TabFolder getTabFolder() { + return fTabFolder; + } + + /** + * Returns the name widget + */ + private Text getNameWidget() { + return fNameWidget; + } + + /** + * Sets the name widget + */ + private void setNameWidget(Text nameText) { + fNameWidget = nameText; + } + + /** + * Sets the current name + */ + public void setName(String name) { + if (getWorkingCopy() != null) { + if (name == null) { + name = ""; //$NON-NLS-1$ + } + getNameWidget().setText(name.trim()); + refreshStatus(); + } + } + + /** + * Sets the control that contains all of this viewer's controls which can be + * hidden/shown. + * + * @param comp + */ + private void setViewerArea(Composite comp) { + fViewerArea = comp; + } + + /** + * Returns the control that contains all of this viewer's controls which can + * be hidden/shown. + */ + protected Composite getViewerArea() { + return fViewerArea; + } + + /** + * @see org.eclipse.jface.viewers.Viewer#getControl() + */ + public Control getControl() { + return fViewerControl; + } + + /** + * Returns the shell this viewer is contained in. + */ + protected Shell getShell() { + return getControl().getShell(); + } + + /** + * @see org.eclipse.jface.viewers.IInputProvider#getInput() + */ + public Object getInput() { + return fInput; + } + + /** + * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection() + */ + public ISelection getSelection() { + if (getActiveTab() == null) { + return new StructuredSelection(); + } else { + return new StructuredSelection(getActiveTab()); + } + } + + /** + * @see org.eclipse.jface.viewers.Viewer#refresh() + */ + public void refresh() { + if (!isInitializingTabs()) { + boolean dirty = isDirty(); + getApplyButton().setEnabled(dirty && canSave()); + getRevertButton().setEnabled(dirty); + // update error ticks + ILaunchConfigurationTab[] tabs = getTabs(); + if (tabs == null) { + return; + } + TabFolder folder = getTabFolder(); + for (int i = 0; i < tabs.length; i++) { + ILaunchConfigurationTab tab = tabs[i]; + boolean error = tab.getErrorMessage() != null; + TabItem item = folder.getItem(i); + setTabIcon(item, error, tab); + } + } + } + + /** + * Set the specified tab item's icon to an error icon if <code>error</code> is true, + * or a transparent icon of the same size otherwise. + */ + private void setTabIcon(TabItem tabItem, boolean error, ILaunchConfigurationTab tab) { + Image image = null; + if (error) { + image = LaunchConfigurationManager.getDefault().getErrorTabImage(tab); + } else { + image = tab.getImage(); + } + tabItem.setImage(image); + } + + /** + * @see org.eclipse.jface.viewers.Viewer#setInput(java.lang.Object) + */ + public void setInput(Object input) { + if (input == null) { + if (fInput == null) { + return; + } else { + inputChanged(input); + } + } else { + if (!input.equals(fInput)) { + inputChanged(input); + } + } + } + + /** + * The input has changed to the given object, possibly <code>null</code>. + * + * @param input the new input, possibly <code>null</code> + */ + protected void inputChanged(Object input) { + fInput = input; + if (input instanceof ILaunchConfiguration) { + ILaunchConfiguration configuration = (ILaunchConfiguration)input; + setOriginal(configuration); + try { + setWorkingCopy(configuration.getWorkingCopy()); + } catch (CoreException e) { + errorDialog(e); + } + displayTabs(); + } else { + setOriginal(null); + setWorkingCopy(null); + getViewerArea().setVisible(false); + disposeExistingTabs(); + } + } + + /** + * Displays tabs for the current working copy + */ + protected void displayTabs() { + // Turn on initializing flag to ignore message updates + setInitializingTabs(true); + + ILaunchConfigurationType type = null; + try { + type = getWorkingCopy().getType(); + showTabsFor(type); + } catch (CoreException e) { + errorDialog(e); + setInitializingTabs(false); + return; + } + + // Update the name field before to avoid verify error + getNameWidget().setText(getWorkingCopy().getName()); + + // Retrieve the current tab group. If there is none, clean up and leave + ILaunchConfigurationTabGroup tabGroup = getTabGroup(); + if (tabGroup == null) { + IStatus status = new Status(IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(), 0, MessageFormat.format("No tabs defined for launch configuration type {0}", new String[]{type.getName()}), null); + CoreException e = new CoreException(status); + errorDialog(e); + setInitializingTabs(false); + return; + } + + // Update the tabs with the new working copy + tabGroup.initializeFrom(getWorkingCopy()); + + // Update the name field after in case client changed it + getNameWidget().setText(getWorkingCopy().getName()); + + // Turn off initializing flag to update message + setInitializingTabs(false); + + refreshStatus(); + } + + /** + * Populate the tabs in the configuration edit area to be appropriate to the current + * launch configuration type. + */ + private void showTabsFor(ILaunchConfigurationType configType) { + + // Don't do any work if the current tabs are for the current config type + if (getTabType() != null && getTabType().equals(configType)) { + return; + } + + // Avoid flicker + getViewerArea().setVisible(false); + + // Dispose the current tabs + disposeExistingTabs(); + + // Build the new tabs + ILaunchConfigurationTabGroup group = null; + try { + group = createGroup(configType); + setTabGroup(group); + } catch (CoreException ce) { + DebugUIPlugin.errorDialog(getShell(), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Error_19"), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Exception_occurred_creating_launch_configuration_tabs_27"),ce); //$NON-NLS-1$ //$NON-NLS-2$ + return; + } + + // Create the Control for each tab + ILaunchConfigurationTab[] tabs = group.getTabs(); + for (int i = 0; i < tabs.length; i++) { + TabItem tab = new TabItem(getTabFolder(), SWT.NONE); + String name = tabs[i].getName(); + if (name == null) { + name = LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.unspecified_28"); //$NON-NLS-1$ + } + tab.setText(name); + Image image = tabs[i].getImage(); + tab.setImage(image); + tabs[i].createControl(tab.getParent()); + Control control = tabs[i].getControl(); + if (control != null) { + tab.setControl(control); + } + } + + setTabGroup(group); + setTabType(configType); + getViewerArea().setVisible(true); + } + + /** + * Returns tab group for the given type of launch configuration. + * Tabs are initialized to be contained in this dialog. + * + * @exception CoreException if unable to instantiate a tab group + */ + protected ILaunchConfigurationTabGroup createGroup(final ILaunchConfigurationType configType) throws CoreException { + // Use a final Object array to store the tab group and any exception that + // results from the Runnable + final Object[] finalArray = new Object[2]; + Runnable runnable = new Runnable() { + public void run() { + ILaunchConfigurationTabGroup tabGroup = null; + try { + tabGroup = LaunchConfigurationPresentationManager.getDefault().getTabGroup(configType); + finalArray[0] = tabGroup; + } catch (CoreException ce) { + finalArray[1] = ce; + return; + } + tabGroup.createTabs(getLaunchConfigurationDialog(), getLaunchConfigurationDialog().getMode()); + ILaunchConfigurationTab[] tabs = tabGroup.getTabs(); + for (int i = 0; i < tabs.length; i++) { + tabs[i].setLaunchConfigurationDialog(getLaunchConfigurationDialog()); + } + } + }; + + // Creating the tabs can result in plugin loading, so we show the busy cursor + BusyIndicator.showWhile(getControl().getDisplay(), runnable); + + // Re-throw any CoreException if there was one + if (finalArray[1] != null) { + throw (CoreException)finalArray[1]; + } + + // Otherwise return the tab group + return (ILaunchConfigurationTabGroup)finalArray[0]; + } + + /** + * @see org.eclipse.jface.viewers.Viewer#setSelection(org.eclipse.jface.viewers.ISelection, boolean) + */ + public void setSelection(ISelection selection, boolean reveal) { + if (getWorkingCopy() != null) { + if (selection instanceof IStructuredSelection) { + IStructuredSelection structuredSelection = (IStructuredSelection)selection; + Object object = structuredSelection.getFirstElement(); + if (object instanceof ILaunchConfigurationTab) { + ILaunchConfigurationTab[] tabs = getTabs(); + for (int i = 0; i < tabs.length; i++) { + ILaunchConfigurationTab tab = tabs[i]; + if (tab.equals(object)) { + fCurrentTabIndex = i; + getTabFolder().setSelection(i); + } + return; + } + } + } + } + + } + + /** + * Returns the tabs currently being displayed, or + * <code>null</code> if none. + * + * @return currently displayed tabs, or <code>null</code> + */ + public ILaunchConfigurationTab[] getTabs() { + if (getTabGroup() != null) { + return getTabGroup().getTabs(); + } + return null; + } + + /** + * Returns the currently active <code>ILaunchConfigurationTab</code> + * being displayed, or <code>null</code> if there is none. + * + * @return currently active <code>ILaunchConfigurationTab</code>, or <code>null</code>. + */ + public ILaunchConfigurationTab getActiveTab() { + TabFolder folder = getTabFolder(); + ILaunchConfigurationTab[] tabs = getTabs(); + if (folder != null && tabs != null) { + int pageIndex = folder.getSelectionIndex(); + if (pageIndex >= 0) { + return tabs[pageIndex]; + } + } + return null; + } + + /** + * Returns whether the launch configuration being edited is dirty (i.e. + * needs saving) + * + * @return whether the launch configuration being edited needs saving + */ + public boolean isDirty() { + ILaunchConfigurationWorkingCopy workingCopy = getWorkingCopy(); + if (workingCopy == null) { + return false; + } + + // Working copy hasn't been saved + if (workingCopy.getOriginal() == null) { + return true; + } + + updateWorkingCopyFromPages(); + ILaunchConfiguration original = getOriginal(); + return !original.contentsEqual(workingCopy); + } + + /** + * Update apply & revert buttons, as well as buttons and message on the + * launch config dialog. + */ + protected void refreshStatus() { + getLaunchConfigurationDialog().updateButtons(); + getLaunchConfigurationDialog().updateMessage(); + } + + /** + * Returns the containing launch dialog + */ + protected ILaunchConfigurationDialog getLaunchConfigurationDialog() { + return fDialog; + } + + /** + * Sets the launch configuration being displayed/edited, possilby + * <code>null</code>. + */ + private void setOriginal(ILaunchConfiguration configuration) { + fOriginal = configuration; + } + + /** + * Returns the original launch configuration being edited, possibly + * <code>null</code>. + * + * @return ILaunchConfiguration + */ + protected ILaunchConfiguration getOriginal() { + return fOriginal; + } + + /** + * Sets the working copy used to edit the original. + */ + private void setWorkingCopy(ILaunchConfigurationWorkingCopy workingCopy) { + fWorkingCopy = workingCopy; + } + + /** + * Returns the working copy used to edit the original, possibly + * <code>null</code>. + */ + protected ILaunchConfigurationWorkingCopy getWorkingCopy() { + return fWorkingCopy; + } + + /** + * Return whether the current configuration can be saved. + * <p> + * Note this is NOT the same thing as the config simply being valid. It + * is possible to save a config that does not validate. This method + * determines whether the config can be saved without causing a serious + * error. For example, a shared config that has no specified location would + * cause this method to return <code>false</code>. + * </p> + */ + public boolean canSave() { + // First make sure that name doesn't prevent saving the config + try { + verifyName(); + } catch (CoreException ce) { + return false; + } + + // Next, make sure none of the tabs object to saving the config + ILaunchConfigurationTab[] tabs = getTabs(); + if (tabs == null) { + return false; + } + for (int i = 0; i < tabs.length; i++) { + if (!tabs[i].canSave()) { + return false; + } + } + return true; + } + + /** + * @see ILaunchConfigurationDialog#canLaunch() + */ + public boolean canLaunch() { + if (getWorkingCopy() == null) { + return false; + } + try { + verifyName(); + } catch (CoreException e) { + return false; + } + + ILaunchConfigurationTab[] tabs = getTabs(); + if (tabs == null) { + return false; + } + for (int i = 0; i < tabs.length; i++) { + if (!tabs[i].isValid(getWorkingCopy())) { + return false; + } + } + return true; + } + + /** + * Returns the current error message or <code>null</code> if none. + */ + public String getErrorMesssage() { + if (getWorkingCopy() == null) { + return null; + } + try { + verifyName(); + } catch (CoreException ce) { + return ce.getStatus().getMessage(); + } + + String message = null; + ILaunchConfigurationTab activeTab = getActiveTab(); + if (activeTab == null) { + return null; + } else { + activeTab.isValid(getWorkingCopy()); + message = activeTab.getErrorMessage(); + } + if (message != null) { + return message; + } + + ILaunchConfigurationTab[] allTabs = getTabs(); + for (int i = 0; i < allTabs.length; i++) { + ILaunchConfigurationTab tab = allTabs[i]; + if (tab == activeTab) { + continue; + } + tab.isValid(getWorkingCopy()); + message = tab.getErrorMessage(); + if (message != null) { + message = '[' + removeAmpersandsFrom(tab.getName()) + "]: " + message; //$NON-NLS-1$ + return message; + } + } + return null; + } + + /** + * Return a copy of the specified string without ampersands. + */ + private String removeAmpersandsFrom(String string) { + String newString = new String(string); + int index = newString.indexOf('&'); + while (index != -1) { + newString = string.substring(0, index) + newString.substring(index + 1, newString.length()); + index = newString.indexOf('&'); + } + return newString; + } + + /** + * Returns the current message or <code>null</code> if none. + */ + public String getMesssage() { + ILaunchConfigurationTab tab = getActiveTab(); + if (tab == null) { + return null; + } else { + return tab.getMessage(); + } + } + + /** + * Verify that the launch configuration name is valid. + */ + protected void verifyName() throws CoreException { + String currentName = getNameWidget().getText().trim(); + + // If there is no name, complain + if (currentName.length() < 1) { + throw new CoreException(new Status(IStatus.ERROR, + DebugUIPlugin.getUniqueIdentifier(), + 0, + LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Name_required_for_launch_configuration_11"), //$NON-NLS-1$ + null)); + } + + // See if name contains any 'illegal' characters + IStatus status = ResourcesPlugin.getWorkspace().validateName(currentName, IResource.FILE); + if (status.getCode() != IStatus.OK) { + throw new CoreException(new Status(IStatus.ERROR, + DebugUIPlugin.getDefault().getDescriptor().getUniqueIdentifier(), + 0, + status.getMessage(), + null)); + } + + // Otherwise, if there's already a config with the same name, complain + if (!getOriginal().getName().equals(currentName)) { + if (getLaunchManager().isExistingLaunchConfigurationName(currentName)) { + throw new CoreException(new Status(IStatus.ERROR, + DebugUIPlugin.getDefault().getDescriptor().getUniqueIdentifier(), + 0, + LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Launch_configuration_already_exists_with_this_name_12"), //$NON-NLS-1$ + null)); + } + } + } + + private void setDisposingTabs(boolean disposing) { + fDisposingTabs = disposing; + } + + private boolean isDisposingTabs() { + return fDisposingTabs; + } + + private void setInitializingTabs(boolean initializing) { + fInitializingTabs = initializing; + } + + private boolean isInitializingTabs() { + return fInitializingTabs; + } + + private void disposeExistingTabs() { + setDisposingTabs(true); + TabItem[] oldTabs = getTabFolder().getItems(); + for (int i = 0; i < oldTabs.length; i++) { + oldTabs[i].dispose(); + } + if (getTabGroup() != null) { + getTabGroup().dispose(); + } + setTabGroup(null); + setTabType(null); + setDisposingTabs(false); + } + + private ILaunchManager getLaunchManager() { + return DebugPlugin.getDefault().getLaunchManager(); + } + + /** + * Returns the type that tabs are currently displayed + * for, or <code>null</code> if none. + * + * @return launch configuration type or <code>null</code> + */ + private ILaunchConfigurationType getTabType() { + return fTabType; + } + + /** + * Sets the type that tabs are currently displayed + * for, or <code>null</code> if none. + * + * @param tabType launch configuration type + */ + private void setTabType(ILaunchConfigurationType tabType) { + fTabType = tabType; + } + + /** + * Sets the current tab group being displayed + * + * @param group the current tab group being displayed + */ + private void setTabGroup(ILaunchConfigurationTabGroup group) { + fTabGroup = group; + } + + /** + * Returns the current tab group + * + * @return the current tab group, or <code>null</code> if none + */ + public ILaunchConfigurationTabGroup getTabGroup() { + return fTabGroup; + } + + /** + * Notification that a tab has been selected + * + * Disallow tab changing when the current tab is invalid. + * Update the config from the tab being left, and refresh + * the tab being entered. + */ + protected void handleTabSelected() { + if (isDisposingTabs()) { + return; + } + ILaunchConfigurationTab[] tabs = getTabs(); + if (fCurrentTabIndex == getTabFolder().getSelectionIndex() || tabs == null || tabs.length == 0 || fCurrentTabIndex > (tabs.length - 1)) { + return; + } + if (fCurrentTabIndex != -1) { + ILaunchConfigurationTab tab = tabs[fCurrentTabIndex]; + ILaunchConfigurationWorkingCopy wc = getWorkingCopy(); + if (wc != null) { + // apply changes when leaving a tab + tab.performApply(wc); + // re-initialize a tab when entering it + getActiveTab().initializeFrom(wc); + } + } + fCurrentTabIndex = getTabFolder().getSelectionIndex(); + SelectionChangedEvent event = new SelectionChangedEvent(this, getSelection()); + fireSelectionChanged(event); + } + + /** + * Notification the name field has been modified + */ + protected void handleNameModified() { + if (getWorkingCopy() != null) { + try { + verifyName(); + getWorkingCopy().rename(getNameWidget().getText().trim()); + } catch (CoreException ce) { + // verification failed + } + // fire selection changed so the launch dialog will update + fireSelectionChanged(new SelectionChangedEvent(this, getSelection())); + } + } + + /** + * Notification that the 'Apply' button has been pressed + */ + protected void handleApplyPressed() { + try { + // trim name + Text widget = getNameWidget(); + widget.setText(widget.getText().trim()); + if (isDirty()) { + getWorkingCopy().doSave(); + } + } catch (CoreException e) { + DebugUIPlugin.errorDialog(getShell(), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Launch_Configuration_Error_46"), LaunchConfigurationsMessages.getString("LaunchConfigurationDialog.Exception_occurred_while_saving_launch_configuration_47"), e); //$NON-NLS-1$ //$NON-NLS-2$ + return; + } + refresh(); + } + + /** + * Notification that the 'Revert' button has been pressed + */ + protected void handleRevertPressed() { + inputChanged(getOriginal()); + } + + /** + * Iterate over the pages to update the working copy + */ + private void updateWorkingCopyFromPages() { + ILaunchConfigurationWorkingCopy workingCopy = getWorkingCopy(); + if (getTabGroup() != null) { + getTabGroup().performApply(workingCopy); + } + } + + /** + * Show an error dialog on the given exception. + * + * @param exception + */ + protected void errorDialog(CoreException exception) { + ErrorDialog.openError(getShell(), null, null, exception.getStatus()); + } +} diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationView.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationView.java new file mode 100644 index 000000000..78de2de02 --- /dev/null +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationView.java @@ -0,0 +1,268 @@ +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 org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.ILaunchConfigurationListener; +import org.eclipse.debug.core.ILaunchConfigurationType; +import org.eclipse.debug.internal.ui.IDebugHelpContextIds; +import org.eclipse.debug.ui.AbstractDebugView; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugView; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.action.Separator; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.viewers.IStructuredSelection; +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.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.IWorkingSetManager; +import org.eclipse.ui.help.WorkbenchHelp; +import org.eclipse.ui.model.WorkbenchViewerSorter; + +/** + * A tree view of launch configurations + */ +public class LaunchConfigurationView extends AbstractDebugView implements ILaunchConfigurationListener { + + private Viewer fViewer; + + /** + * The launch group to display + */ + private LaunchGroupExtension fLaunchGroup; + + /** + * Actions + */ + private CreateLaunchConfigurationAction fCreateAction; + private DeleteLaunchConfigurationAction fDeleteAction; + private DuplicateLaunchConfigurationAction fDuplicateAction; + + /** + * Manager for working set related a actions. + */ + private LaunchConfigurationWorkingSetActionManager fWorkingSetActionManager; + + /** + * Constructs a launch configuration view for the given launch group + */ + public LaunchConfigurationView(LaunchGroupExtension launchGroup) { + super(); + fLaunchGroup = launchGroup; + } + + /** + * Returns the launch group this view is displaying. + * + * @return the launch group this view is displaying + */ + protected LaunchGroupExtension getLaunchGroup() { + return fLaunchGroup; + } + + /** + * @see org.eclipse.debug.ui.AbstractDebugView#createViewer(org.eclipse.swt.widgets.Composite) + */ + protected Viewer createViewer(Composite parent) { + TreeViewer treeViewer = new TreeViewer(parent); + treeViewer.setLabelProvider(DebugUITools.newDebugModelPresentation()); + treeViewer.setSorter(new WorkbenchViewerSorter()); + treeViewer.setContentProvider(new LaunchConfigurationTreeContentProvider(fLaunchGroup.getMode(), parent.getShell())); + treeViewer.addFilter(new LaunchGroupFilter(getLaunchGroup())); + treeViewer.setInput(ResourcesPlugin.getWorkspace().getRoot()); + treeViewer.expandAll(); + DebugPlugin.getDefault().getLaunchManager().addLaunchConfigurationListener(this); + + IPropertyChangeListener titleUpdater= new IPropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + String property= event.getProperty(); + if (IWorkingSetManager.CHANGE_WORKING_SET_NAME_CHANGE.equals(property)) { + // TODO: tooltip + //updateTreeLabelTooltip(); + } + } + }; + setWorkingSetActionManager(new LaunchConfigurationWorkingSetActionManager(treeViewer, parent.getShell(), titleUpdater)); + + return treeViewer; + } + + /** + * @see org.eclipse.debug.ui.AbstractDebugView#createActions() + */ + protected void createActions() { + + fCreateAction = new CreateLaunchConfigurationAction(getViewer()); + setAction(CreateLaunchConfigurationAction.ID_CREATE_ACTION, fCreateAction); + + fDeleteAction = new DeleteLaunchConfigurationAction(getViewer()); + setAction(DeleteLaunchConfigurationAction.ID_DELETE_ACTION, fDeleteAction); + setAction(IDebugView.REMOVE_ACTION, fDeleteAction); + + fDuplicateAction = new DuplicateLaunchConfigurationAction(getViewer()); + setAction(DuplicateLaunchConfigurationAction.ID_DUPLICATE_ACTION, fDuplicateAction); + + } + + /** + * @see org.eclipse.debug.ui.AbstractDebugView#getHelpContextId() + */ + protected String getHelpContextId() { + return IDebugHelpContextIds.LAUNCH_CONFIGURATION_VIEW; + } + + /** + * @see org.eclipse.debug.ui.AbstractDebugView#fillContextMenu(org.eclipse.jface.action.IMenuManager) + */ + protected void fillContextMenu(IMenuManager menu) { + menu.add(fCreateAction); + menu.add(fDuplicateAction); + menu.add(fDeleteAction); + menu.add(new Separator()); + getWorkingSetActionManager().contributeToMenu(menu); + } + + /** + * @see org.eclipse.debug.ui.AbstractDebugView#configureToolBar(org.eclipse.jface.action.IToolBarManager) + */ + protected void configureToolBar(IToolBarManager tbm) { + } + + /** + * Returns this view's tree viewer + * + * @return this view's tree viewer + */ + protected TreeViewer getTreeViewer() { + return (TreeViewer)getViewer(); + } + + /** + * @see org.eclipse.ui.IWorkbenchPart#dispose() + */ + public void dispose() { + getWorkingSetActionManager().dispose(); + fCreateAction.dispose(); + fDeleteAction.dispose(); + fDuplicateAction.dispose(); + DebugPlugin.getDefault().getLaunchManager().removeLaunchConfigurationListener(this); + } + + /** + * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationAdded(org.eclipse.debug.core.ILaunchConfiguration) + */ + public void launchConfigurationAdded(ILaunchConfiguration configuration) { + try { + getTreeViewer().add(configuration.getType(), configuration); + } catch (CoreException e) { + } + getTreeViewer().setSelection(new StructuredSelection(configuration), true); + } + + /** + * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationChanged(org.eclipse.debug.core.ILaunchConfiguration) + */ + public void launchConfigurationChanged(ILaunchConfiguration configuration) { + } + + /** + * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationRemoved(org.eclipse.debug.core.ILaunchConfiguration) + */ + public void launchConfigurationRemoved(ILaunchConfiguration configuration) { + ILaunchConfigurationType type = null; + int typeIndex= -1; // The index of the deleted configuration's type + int configIndex= -1; // The index of the deleted configuration + // Initialize data used to set the selection after deletion + TreeItem[] items= getTreeViewer().getTree().getItems(); + TreeItem typeItem; + for (int i= 0, numTypes= items.length; (i < numTypes && type == null); i++) { + typeItem= items[i]; + typeIndex= i; + TreeItem[] configs= typeItem.getItems(); + for (int j= 0, numConfigs= configs.length; j < numConfigs; j++) { + if (configuration.equals(configs[j].getData())) { + configIndex= j; + type = (ILaunchConfigurationType)typeItem.getData(); + break; + } + } + } + + getTreeViewer().remove(configuration); + if (getViewer().getSelection().isEmpty()) { + IStructuredSelection newSelection= null; + if (typeIndex != -1 && configIndex != -1) { + // Reset selection to the next config + TreeItem[] configItems= getTreeViewer().getTree().getItems()[typeIndex].getItems(); + int numItems= configItems.length; + if (numItems > configIndex) { // Select the item at the same index as the deleted + newSelection= new StructuredSelection(configItems[configIndex].getData()); + } else if (numItems > 0) { // Deleted the last item(s). Select the last item + newSelection= new StructuredSelection(configItems[numItems - 1].getData()); + } + } + if (newSelection == null && type != null) { + // Reset selection to the config type of the first selected configuration + newSelection = new StructuredSelection(type); + } + getTreeViewer().setSelection(newSelection); + } + } + + /** + * This is similar to IWorkbenchPart#createPartControl(Composite), but it is + * called by the launch dialog when creating the launch config tree view. + * Since this view is not contained in the workbench, we cannot do all the + * usual initialzation (toolbars, etc). + */ + public void createLaunchDialogControl(Composite parent) { + fViewer = createViewer(parent); + createActions(); + createContextMenu(getViewer().getControl()); + WorkbenchHelp.setHelp(parent, getHelpContextId()); + getViewer().getControl().addKeyListener(new KeyAdapter() { + public void keyPressed(KeyEvent e) { + handleKeyPressed(e); + } + }); + if (getViewer() instanceof StructuredViewer) { + ((StructuredViewer)getViewer()).addDoubleClickListener(this); + } + } + + + + /** + * @see org.eclipse.debug.ui.IDebugView#getViewer() + */ + public Viewer getViewer() { + return fViewer; + } + + private void setWorkingSetActionManager(LaunchConfigurationWorkingSetActionManager actionManager) { + fWorkingSetActionManager = actionManager; + } + + protected LaunchConfigurationWorkingSetActionManager getWorkingSetActionManager() { + return fWorkingSetActionManager; + } + + + +} diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationWorkingSetActionManager.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationWorkingSetActionManager.java index d50bb0432..eafe1f79b 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationWorkingSetActionManager.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationWorkingSetActionManager.java @@ -276,7 +276,7 @@ public class LaunchConfigurationWorkingSetActionManager { fTitleUpdater = titleUpdater; } - private IPropertyChangeListener getTitleUpdater() { + protected IPropertyChangeListener getTitleUpdater() { return fTitleUpdater; } 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 diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/AbstractDebugView.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/AbstractDebugView.java index a5231e4ae..070f35f54 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/AbstractDebugView.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/AbstractDebugView.java @@ -345,7 +345,9 @@ public abstract class AbstractDebugView extends PageBookView implements IDebugVi menuControl.setMenu(menu); // register the context menu such that other plugins may contribute to it - getSite().registerContextMenu(menuMgr, getViewer()); + if (getSite() != null) { + getSite().registerContextMenu(menuMgr, getViewer()); + } addContextMenuManager(menuMgr); } diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/DebugUITools.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/DebugUITools.java index 22e515cb4..7bb757b0d 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/DebugUITools.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/DebugUITools.java @@ -31,20 +31,8 @@ import org.eclipse.debug.internal.ui.DebugUIPlugin; import org.eclipse.debug.internal.ui.DefaultLabelProvider; import org.eclipse.debug.internal.ui.DelegatingModelPresentation; import org.eclipse.debug.internal.ui.LazyModelPresentation; -import org - .eclipse - .debug - .internal - .ui - .launchConfigurations - .LaunchConfigurationDialog; -import org - .eclipse - .debug - .internal - .ui - .launchConfigurations - .LaunchConfigurationManager; +import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationManager; +import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.preference.IPreferenceStore; @@ -52,6 +40,7 @@ import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.window.Window; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchPage; @@ -315,13 +304,14 @@ public class DebugUITools { * @since 2.1 */ public static int openLaunchConfigurationDialogOnGroup(Shell shell, IStructuredSelection selection, String groupIdentifier) { - LaunchConfigurationDialog dialog = (LaunchConfigurationDialog) LaunchConfigurationDialog.getCurrentlyVisibleLaunchConfigurationDialog(); + LaunchConfigurationsDialog dialog = (LaunchConfigurationsDialog) LaunchConfigurationsDialog.getCurrentlyVisibleLaunchConfigurationDialog(); if (dialog != null) { - dialog.setTreeViewerSelection(selection); - return LaunchConfigurationDialog.LAUNCH_CONFIGURATION_DIALOG_REUSE_OPEN; + dialog.setInitialSelection(selection); + dialog.doInitialTreeSelection(); + return Window.OK; } else { - dialog = new LaunchConfigurationDialog(shell, null, LaunchConfigurationManager.getDefault().getLaunchGroup(groupIdentifier)); - dialog.setOpenMode(LaunchConfigurationDialog.LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_SELECTION); + dialog = new LaunchConfigurationsDialog(shell, null, LaunchConfigurationManager.getDefault().getLaunchGroup(groupIdentifier)); + dialog.setOpenMode(LaunchConfigurationsDialog.LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_SELECTION); dialog.setInitialSelection(selection); return dialog.open(); } |