/*
* Copyright 2012 Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.tools.debug.ui.internal.dialogs;
import com.google.dart.tools.debug.core.DartDebugCorePlugin;
import com.google.dart.tools.debug.ui.internal.DartDebugUIPlugin;
import com.google.dart.tools.debug.ui.internal.DartUtil;
import com.google.dart.tools.debug.ui.internal.DebugErrorHandler;
import com.google.dart.tools.debug.ui.internal.util.LaunchUtils;
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.ILaunchConfigurationListener;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
import org.eclipse.debug.internal.ui.launchConfigurations.DeleteLaunchConfigurationAction;
import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationPresentationManager;
import org.eclipse.debug.ui.ILaunchConfigurationDialog;
import org.eclipse.debug.ui.ILaunchConfigurationTab;
import org.eclipse.debug.ui.ILaunchConfigurationTabGroup;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
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.TableViewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
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.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.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.internal.WorkbenchPlugin;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
/**
* A dialog to create, edit, and manage launch configurations.
*/
@SuppressWarnings("restriction")
public class ManageLaunchesDialog extends TitleAreaDialog implements ILaunchConfigurationDialog,
ILaunchConfigurationListener {
/**
* Asynchronously open the manage launches dialog with the given launch automatically selected.
*/
public static void openAsync(final IWorkbenchWindow window, final ILaunchConfiguration config) {
final Display display = Display.getDefault();
display.asyncExec(new Runnable() {
@Override
public void run() {
final ManageLaunchesDialog dialog = new ManageLaunchesDialog(window);
dialog.selectLaunchOnOpen(config);
dialog.open();
}
});
}
private IWorkbenchWindow window;
private TableViewer launchesViewer;
private Composite configUI;
private ScrolledComposite launchConfigArea;
private Text configNameText;
private ILaunchConfiguration selectedConfig;
private ILaunchConfigurationWorkingCopy workingCopy;
private ILaunchConfigurationTabGroup currentTabGroup;
private ILaunchConfigurationTab activeTab;
private IAction deleteAction;
private ILaunchConfiguration launchConfig;
public ManageLaunchesDialog(IWorkbenchWindow window) {
super(window.getShell());
this.window = window;
setShellStyle(getShellStyle() | SWT.RESIZE);
}
public boolean canLaunch() {
if (workingCopy == 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(workingCopy)) {
return false;
}
}
return true;
}
@Override
public String generateName(String name) {
if (name == null) {
name = IInternalDebugCoreConstants.EMPTY_STRING;
}
return getLaunchManager().generateLaunchConfigurationName(name);
}
@Override
public ILaunchConfigurationTab getActiveTab() {
return activeTab;
}
@Override
public String getMode() {
return ILaunchManager.RUN_MODE;
}
@Override
public ILaunchConfigurationTab[] getTabs() {
return currentTabGroup.getTabs();
}
@Override
public void launchConfigurationAdded(ILaunchConfiguration configuration) {
ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
if (selectedConfig != null && selectedConfig.equals(manager.getMovedFrom(configuration))) {
// this config was re-named, update the dialog with the new config
selectedConfig = configuration;
selectLaunchConfiguration(selectedConfig.getName());
}
refreshLaunchesViewer();
}
@Override
public void launchConfigurationChanged(ILaunchConfiguration configuration) {
getShell().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
Shell shell = getShell();
if (shell != null && !shell.isDisposed()) {
updateButtons();
updateMessage();
}
}
});
}
@Override
public void launchConfigurationRemoved(ILaunchConfiguration configuration) {
try {
getShell().setRedraw(false);
if (configuration == selectedConfig) {
closeConfig(true);
refreshLaunchesViewer();
selectFirstLaunchConfig();
} else {
refreshLaunchesViewer();
}
} finally {
getShell().setRedraw(true);
}
}
@Override
public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable)
throws InvocationTargetException, InterruptedException {
throw new UnsupportedOperationException("run()");
}
public void selectLaunchConfiguration(String name) {
saveConfig();
ILaunchConfiguration config = getConfigurationNamed(name);
if (config != null) {
launchesViewer.setSelection(new StructuredSelection(config));
}
}
/**
* Select the specified launch configuration when the dialog opens.
*/
public void selectLaunchOnOpen(ILaunchConfiguration config) {
selectedConfig = config;
}
@Override
public void setActiveTab(ILaunchConfigurationTab tab) {
if (activeTab != null) {
activeTab.deactivated(workingCopy);
activeTab.getControl().dispose();
}
activeTab = tab;
if (activeTab != null) {
launchConfigArea.setRedraw(false);
configNameText.setVisible(true);
activeTab.createControl(launchConfigArea);
// GridDataFactory.swtDefaults().grab(true, false).align(SWT.FILL, SWT.BEGINNING).applyTo(
// activeTab.getControl());
launchConfigArea.setContent(activeTab.getControl());
activeTab.getControl().setSize(activeTab.getControl().computeSize(SWT.DEFAULT, SWT.DEFAULT));
configUI.layout(true);
activeTab.activated(workingCopy);
launchConfigArea.setRedraw(true);
} else {
configNameText.setVisible(false);
}
updateButtons();
updateMessage();
}
@Override
public void setActiveTab(int index) {
setActiveTab(getTabs()[index]);
}
@Override
public void setName(String name) {
configNameText.setText(name);
}
@Override
public void updateButtons() {
if (getButton(IDialogConstants.OK_ID) != null) {
// Apply button
getButton(IDialogConstants.CLIENT_ID).setEnabled(canEnableButton());
// Run button
getButton(IDialogConstants.OK_ID).setEnabled(canEnableButton());
// Delete action
getDeleteAction().setEnabled(selectedConfig != null);
}
}
@Override
public void updateMessage() {
try {
verifyName();
} catch (CoreException ce) {
setErrorMessage(ce.getStatus().getMessage());
return;
}
if (activeTab != null) {
String errorMessage = activeTab.getErrorMessage();
if (errorMessage != null) {
setErrorMessage(errorMessage);
} else {
setMessage(activeTab.getMessage());
setErrorMessage(null);
}
} else {
setMessage(null);
setErrorMessage(null);
}
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(Messages.ManageLaunchesDialog_createLaunch);
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
// Close
createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CLOSE_LABEL, false);
// Apply
createButton(parent, IDialogConstants.CLIENT_ID, "Apply", false);
getButton(IDialogConstants.CLIENT_ID).addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
handleApplyButton();
}
});
// Run
createButton(parent, IDialogConstants.OK_ID, Messages.ManageLaunchesDialog_launchRun, true);
updateButtons();
}
@Override
protected Control createDialogArea(Composite parent) {
Composite contents = (Composite) super.createDialogArea(parent);
setTitle(Messages.ManageLaunchesDialog_manageLaunches);
setTitleImage(DartDebugUIPlugin.getImage("wiz/run_wiz.png")); //$NON-NLS-1$
Composite composite = new Composite(contents, SWT.NONE);
GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(composite);
createDialogUI(composite);
DebugPlugin.getDefault().getLaunchManager().addLaunchConfigurationListener(this);
parent.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
DebugPlugin.getDefault().getLaunchManager().removeLaunchConfigurationListener(
ManageLaunchesDialog.this);
}
});
return contents;
}
@Override
protected IDialogSettings getDialogBoundsSettings() {
final String settingsName = getClass().getCanonicalName();
IDialogSettings workbenchSettings = WorkbenchPlugin.getDefault().getDialogSettings();
IDialogSettings section = workbenchSettings.getSection(settingsName);
if (DartDebugCorePlugin.getPlugin().getClearDialogSettings()) {
section = null;
DartDebugCorePlugin.getPlugin().setClearLaunchesDialogSettings(false);
}
if (section == null) {
section = workbenchSettings.addNewSection(settingsName);
}
return section;
}
@Override
protected int getDialogBoundsStrategy() {
return DIALOG_PERSISTSIZE;
}
/**
* Returns the current launch manager
*
* @return the current launch manager
*/
protected ILaunchManager getLaunchManager() {
return DebugPlugin.getDefault().getLaunchManager();
}
protected void handleApplyButton() {
saveConfig();
}
protected void handleSelectedConfigChanged() {
closeConfig(false);
ILaunchConfiguration sel = null;
if (launchesViewer.getSelection() instanceof IStructuredSelection) {
Object obj = ((IStructuredSelection) launchesViewer.getSelection()).getFirstElement();
if (obj instanceof ILaunchConfiguration) {
sel = (ILaunchConfiguration) obj;
}
}
selectedConfig = sel;
updateButtons();
updateMessage();
if (selectedConfig != null) {
show(selectedConfig);
}
}
@Override
protected void okPressed() {
saveConfig();
boolean supportsDebug = false;
try {
supportsDebug = selectedConfig.supportsMode(ILaunchManager.DEBUG_MODE);
} catch (CoreException e) {
}
if (supportsDebug) {
LaunchUtils.launch(selectedConfig, ILaunchManager.DEBUG_MODE);
} else {
LaunchUtils.launch(selectedConfig, ILaunchManager.RUN_MODE);
}
super.okPressed();
}
private boolean canEnableButton() {
return activeTab != null && activeTab.getErrorMessage() == null && canLaunch();
}
private void closeConfig(boolean terminate) {
if (!terminate) {
saveConfig();
}
setActiveTab(null);
activeTab = null;
selectedConfig = null;
currentTabGroup = null;
workingCopy = null;
}
private void createDialogUI(Composite parent) {
GridLayoutFactory.fillDefaults().margins(12, 6).applyTo(parent);
SashForm sashForm = new SashForm(parent, SWT.HORIZONTAL);
GridDataFactory.fillDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).hint(725, 415).applyTo(
sashForm);
Composite leftComposite = new Composite(sashForm, SWT.NONE);
GridLayoutFactory.fillDefaults().applyTo(leftComposite);
GridDataFactory.swtDefaults().grab(false, true).align(SWT.FILL, SWT.FILL).applyTo(leftComposite);
ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
ToolBar toolBar = toolBarManager.createControl(leftComposite);
toolBar.setBackground(parent.getBackground());
GridDataFactory.swtDefaults().grab(true, false).align(SWT.BEGINNING, SWT.FILL).applyTo(toolBar);
launchesViewer = new TableViewer(leftComposite, SWT.MULTI | SWT.V_SCROLL | SWT.BORDER);
launchesViewer.setLabelProvider(new DelegatingStyledCellLabelProvider(
new LaunchConfigLabelProvider()));
launchesViewer.setComparator(new ViewerComparator(String.CASE_INSENSITIVE_ORDER));
launchesViewer.setContentProvider(new LaunchConfigContentProvider());
launchesViewer.setInput(ResourcesPlugin.getWorkspace().getRoot());
launchesViewer.getTable().setFocus();
launchesViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
handleSelectedConfigChanged();
}
});
GridDataFactory.swtDefaults().grab(false, true).align(SWT.FILL, SWT.FILL).hint(50, 50).applyTo(
launchesViewer.getControl());
ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
for (final ILaunchConfigurationType configType : manager.getLaunchConfigurationTypes()) {
CreateLaunchAction action = new CreateLaunchAction(this, configType);
toolBarManager.add(action);
}
//toolBarManager.add(new Separator());
toolBarManager.add(getDeleteAction());
toolBarManager.update(true);
configUI = new Composite(sashForm, SWT.NONE);
GridLayoutFactory.fillDefaults().applyTo(configUI);
GridDataFactory.swtDefaults().grab(true, false).align(SWT.FILL, SWT.BEGINNING).applyTo(configUI);
toolBar.pack();
Label toolbarSpacer = new Label(configUI, SWT.NONE);
GridDataFactory.swtDefaults().hint(SWT.NONE, toolBar.getSize().y).applyTo(toolbarSpacer);
Composite nameComposite = new Composite(configUI, SWT.NONE);
GridDataFactory.swtDefaults().grab(true, false).align(SWT.FILL, SWT.FILL).applyTo(nameComposite);
GridLayoutFactory.swtDefaults().margins(6, 0).applyTo(nameComposite);
configNameText = new Text(nameComposite, SWT.SINGLE | SWT.BORDER);
GridDataFactory.swtDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).applyTo(
configNameText);
configNameText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
if (workingCopy != null) {
workingCopy.rename(configNameText.getText());
}
}
});
launchConfigArea = new ScrolledComposite(configUI, SWT.V_SCROLL);
GridDataFactory.swtDefaults().grab(true, true).align(SWT.FILL, SWT.FILL).applyTo(
launchConfigArea);
launchConfigArea.setExpandVertical(false);
launchConfigArea.setExpandHorizontal(true);
configNameText.setVisible(false);
sashForm.setWeights(new int[] {33, 67});
selectLaunchConfigFromPage();
}
private ILaunchConfiguration getConfigurationNamed(String name) {
try {
for (ILaunchConfiguration config : DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations()) {
if (name.equals(config.getName())) {
return config;
}
}
} catch (CoreException exception) {
DartUtil.logError(exception);
}
return null;
}
private IAction getDeleteAction() {
if (deleteAction == null) {
deleteAction = new DeleteLaunchConfigurationAction(launchesViewer, getMode());
}
return deleteAction;
}
private void refreshLaunchesViewer() {
launchesViewer.refresh();
}
private void refreshTable() {
launchesViewer.refresh();
}
private void saveConfig() {
if (currentTabGroup != null) {
currentTabGroup.performApply(workingCopy);
try {
workingCopy.doSave();
} catch (CoreException e) {
DebugErrorHandler.errorDialog(
getShell(),
"Error Saving Launch",
"Unable to save launch settings: " + e.toString(),
e);
}
}
updateButtons();
updateMessage();
refreshTable();
}
private void selectFirstLaunchConfig() {
final ILaunchConfiguration launchConfig = (ILaunchConfiguration) launchesViewer.getElementAt(0);
if (launchConfig != null && launchesViewer.getSelection().isEmpty()) {
launchesViewer.setSelection(new StructuredSelection(launchConfig));
}
}
private void selectLaunchConfigFromPage() {
ILaunchConfiguration config = selectedConfig;
if (config == null) {
IResource resource = LaunchUtils.getSelectedResource(window);
if (resource != null) {
List<ILaunchConfiguration> configs = LaunchUtils.getExistingLaunchesFor(resource);
if (!configs.isEmpty()) {
config = configs.get(0);
}
}
}
if (config != null) {
launchesViewer.setSelection(new StructuredSelection(config));
} else {
selectFirstLaunchConfig();
}
}
private void show(ILaunchConfiguration config) {
try {
launchConfig = config;
workingCopy = launchConfig.getWorkingCopy();
configNameText.setText(workingCopy.getName());
currentTabGroup = LaunchConfigurationPresentationManager.getDefault().getTabGroup(
workingCopy,
getMode());
currentTabGroup.createTabs(this, getMode());
ILaunchConfigurationTab[] tabs = currentTabGroup.getTabs();
for (int i = 0; i < tabs.length; i++) {
tabs[i].setLaunchConfigurationDialog(this);
}
setActiveTab(0);
} catch (CoreException ce) {
DebugErrorHandler.errorDialog(
getShell(),
"Error Displaying Launch",
"Unable to display launch settings: " + ce.toString(),
ce);
}
}
/**
* Verify that the launch configuration name is valid.
*/
private void verifyName() throws CoreException {
if (configNameText.isVisible()) {
ILaunchManager mgr = getLaunchManager();
String currentName = configNameText.getText().trim();
// If there is no name, complain
if (currentName.length() < 1) {
throw new CoreException(new Status(
IStatus.ERROR,
DartDebugUIPlugin.PLUGIN_ID,
0,
Messages.ManageLaunchesDialog_Name_required_for_launch_configuration,
null));
}
try {
mgr.isValidLaunchConfigurationName(currentName);
} catch (IllegalArgumentException iae) {
throw new CoreException(new Status(
IStatus.ERROR,
DartDebugUIPlugin.PLUGIN_ID,
0,
iae.getMessage(),
null));
}
// Otherwise, if there's already a config with the same name, complain
if (!launchConfig.getName().equals(currentName)) {
if (mgr.isExistingLaunchConfigurationName(currentName)) {
throw new CoreException(new Status(
IStatus.ERROR,
DartDebugUIPlugin.PLUGIN_ID,
0,
Messages.ManageLaunchesDialog_Launch_configuration_already_exists_with_this_name,
null));
}
}
}
}
}