/******************************************************************************* * Copyright (c) 2009, 2010 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * QNX Software Systems - initial API and implementation * Freescale Semiconductor *******************************************************************************/ package org.eclipse.cdt.launch.internal.ui; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import org.eclipse.cdt.launch.internal.MultiLaunchConfigurationDelegate; import org.eclipse.cdt.launch.internal.MultiLaunchConfigurationDelegate.LaunchElement; import org.eclipse.cdt.launch.internal.MultiLaunchConfigurationDelegate.LaunchElement.EPostLaunchAction; import org.eclipse.cdt.launch.ui.ComboControlledStackComposite; 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.ILaunchManager; import org.eclipse.debug.internal.ui.DebugUIPlugin; import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationFilteredTree; import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationManager; import org.eclipse.debug.internal.ui.launchConfigurations.LaunchGroupFilter; import org.eclipse.debug.ui.ILaunchGroup; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.TitleAreaDialog; 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.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.swt.SWT; 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.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; 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.Text; import org.eclipse.swt.widgets.Tree; import org.eclipse.ui.dialogs.FilteredTree; import org.eclipse.ui.dialogs.PatternFilter; /** * Dialog to select launch configuration(s) */ public class MultiLaunchConfigurationSelectionDialog extends TitleAreaDialog implements ISelectionChangedListener { private ViewerFilter[] fFilters = null; private ISelection fSelection; private ILaunchGroup[] launchGroups; private String mode; private EPostLaunchAction action = EPostLaunchAction.NONE; private Object actionParam; private boolean isDefaultMode; private ViewerFilter emptyTypeFilter; private IStructuredSelection fInitialSelection; private ComboControlledStackComposite fStackComposite; private Label fDelayAmountLabel; private Text fDelayAmountWidget; // in seconds private boolean fForEditing; // true if dialog was opened to edit an entry, otherwise it was opened to add one public MultiLaunchConfigurationSelectionDialog(Shell shell, String initMode, boolean forEditing) { super(shell); LaunchConfigurationManager manager = DebugUIPlugin.getDefault().getLaunchConfigurationManager(); launchGroups = manager.getLaunchGroups(); mode = initMode; fForEditing = forEditing; fFilters = null; setShellStyle(getShellStyle() | SWT.RESIZE); emptyTypeFilter = new ViewerFilter() { public boolean select(Viewer viewer, Object parentElement, Object element) { if (element instanceof ILaunchConfigurationType) { try { ILaunchConfigurationType type = (ILaunchConfigurationType) element; return getLaunchManager().getLaunchConfigurations(type).length > 0; } catch (CoreException e) { return false; } } else if (element instanceof ILaunchConfiguration) { return MultiLaunchConfigurationDelegate.isValidLaunchReference((ILaunchConfiguration) element); } return true; } }; } protected ILaunchManager getLaunchManager() { return DebugPlugin.getDefault().getLaunchManager(); } protected Control createContents(Composite parent) { Control x = super.createContents(parent); validate(); setErrorMessage(null); return x; } protected Control createDialogArea(Composite parent2) { Composite comp = (Composite) super.createDialogArea(parent2); // title bar getShell().setText(fForEditing ? LaunchMessages.MultiLaunchConfigurationSelectionDialog_13 : LaunchMessages.MultiLaunchConfigurationSelectionDialog_12); // dialog message area (not title bar) setTitle(fForEditing ? LaunchMessages.MultiLaunchConfigurationSelectionDialog_15 : LaunchMessages.MultiLaunchConfigurationSelectionDialog_14); fStackComposite = new ComboControlledStackComposite(comp, SWT.NONE); HashMap<String, ILaunchGroup> modes = new HashMap<String, ILaunchGroup>(); for (ILaunchGroup launchGroup : launchGroups) { if (!modes.containsKey(launchGroup.getMode())) { modes.put(launchGroup.getMode(), launchGroup); } } if (this.mode.equals(MultiLaunchConfigurationDelegate.DEFAULT_MODE)) { try { this.mode = "run"; //$NON-NLS-1$ ILaunchConfiguration[] configs = getSelectedLaunchConfigurations(); if (configs.length > 0) { // we care only about the first selected element for (Iterator<String> iterator = modes.keySet().iterator(); iterator.hasNext();) { String mode = iterator.next(); if (configs[0].supportsMode(mode)) { this.mode = mode; break; } } } } catch (Exception e) { } } for (Iterator<String> iterator = modes.keySet().iterator(); iterator.hasNext();) { String mode = iterator.next(); ILaunchGroup launchGroup = modes.get(mode); LaunchConfigurationFilteredTree fTree = new LaunchConfigurationFilteredTree(fStackComposite.getStackParent(), SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER, new PatternFilter(), launchGroup, fFilters); String label = mode; fStackComposite.addItem(label, fTree); fTree.createViewControl(); ViewerFilter[] filters = fTree.getViewer().getFilters(); for (ViewerFilter viewerFilter : filters) { if (viewerFilter instanceof LaunchGroupFilter) { fTree.getViewer().removeFilter(viewerFilter); } } fTree.getViewer().addFilter(emptyTypeFilter); fTree.getViewer().addSelectionChangedListener(this); if (launchGroup.getMode().equals(this.mode)) { fStackComposite.setSelection(label); } if (fInitialSelection!=null) { fTree.getViewer().setSelection(fInitialSelection, true); } } fStackComposite.setLabelText(LaunchMessages.MultiLaunchConfigurationSelectionDialog_4); fStackComposite.pack(); Rectangle bounds = fStackComposite.getBounds(); // adjust size GridData data = ((GridData) fStackComposite.getLayoutData()); if (data == null) { data = new GridData(GridData.FILL_BOTH); fStackComposite.setLayoutData(data); } data.heightHint = Math.max(convertHeightInCharsToPixels(15), bounds.height); data.widthHint = Math.max(convertWidthInCharsToPixels(40), bounds.width); fStackComposite.getCombo().addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { mode = ((Combo) e.widget).getText(); } }); // "Use default mode" checkbox. Use a parent composite to provide consistent left-side padding Composite checkboxComp = new Composite(comp, SWT.NONE); checkboxComp.setLayout(new GridLayout(1, false)); checkboxComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Button checkBox = new Button(checkboxComp, SWT.CHECK); checkBox.setText(LaunchMessages.MultiLaunchConfigurationSelectionDialog_5); checkBox.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { isDefaultMode = ((Button) e.widget).getSelection(); } }); checkBox.setSelection(isDefaultMode); createPostLaunchControl(comp); return comp; } private void createPostLaunchControl(Composite parent) { Composite comp = new Composite(parent, SWT.NONE); comp.setLayout(new GridLayout(4, false)); comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Label label = new Label(comp, SWT.NONE); label.setText(LaunchMessages.MultiLaunchConfigurationSelectionDialog_8); Combo combo = new Combo(comp, SWT.READ_ONLY); combo.add(LaunchElement.actionEnumToStr(EPostLaunchAction.NONE)); combo.add(LaunchElement.actionEnumToStr(EPostLaunchAction.WAIT_FOR_TERMINATION)); combo.add(LaunchElement.actionEnumToStr(EPostLaunchAction.DELAY)); combo.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { final String actionStr = ((Combo) e.widget).getText(); action = MultiLaunchConfigurationDelegate.LaunchElement.strToActionEnum(actionStr); showHideDelayAmountWidgets(); validate(); } }); combo.setText(MultiLaunchConfigurationDelegate.LaunchElement.actionEnumToStr(action)); fDelayAmountLabel = new Label(comp, SWT.NONE); fDelayAmountLabel.setText(LaunchMessages.MultiLaunchConfigurationSelectionDialog_9); fDelayAmountWidget = new Text(comp, SWT.SINGLE | SWT.BORDER); GridData gridData = new GridData(); gridData.widthHint = convertWidthInCharsToPixels(8); fDelayAmountWidget.setLayoutData(gridData); fDelayAmountWidget.addModifyListener(new ModifyListener(){ public void modifyText(ModifyEvent e) { String text = ((Text)e.widget).getText(); try { actionParam = new Integer(Integer.parseInt(text)); } catch (NumberFormatException exc) { actionParam = null; } validate(); } }); if (actionParam instanceof Integer) { fDelayAmountWidget.setText(((Integer)actionParam).toString()); } showHideDelayAmountWidgets(); } private void showHideDelayAmountWidgets() { final boolean visible = action == EPostLaunchAction.DELAY; fDelayAmountLabel.setVisible(visible); fDelayAmountWidget.setVisible(visible); } public ILaunchConfiguration[] getSelectedLaunchConfigurations() { List<ILaunchConfiguration> configs = new ArrayList<ILaunchConfiguration>(); if (fSelection != null && !fSelection.isEmpty()) { for (Iterator<?> iter = ((IStructuredSelection)fSelection).iterator(); iter.hasNext();) { Object selection = iter.next(); if (selection instanceof ILaunchConfiguration) { configs.add((ILaunchConfiguration)selection); } } } return configs.toArray(new ILaunchConfiguration[configs.size()]); } public String getMode() { return isDefaultMode ? MultiLaunchConfigurationDelegate.DEFAULT_MODE : mode; } public EPostLaunchAction getAction(){ return action; } public Object getActionParam(){ return actionParam; } public static MultiLaunchConfigurationSelectionDialog createDialog(Shell shell, String groupId, boolean forEditing) { return new MultiLaunchConfigurationSelectionDialog(shell, groupId, forEditing); } /* (non-Javadoc) * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ public void selectionChanged(SelectionChangedEvent event) { // This listener gets called for a selection change in the launch // configuration viewer embedded in the dialog. Problem is, there are // numerous viewers--one for each platform debug ILaunchGroup (run, // debug, profile). These viewers are stacked, so only one is ever // visible to the user. During initialization, we get a selection change // notification for every viewer. We need to ignore all but the one that // matters--the visible one. Tree topTree = null; final Control topControl = fStackComposite.getTopControl(); if (topControl instanceof FilteredTree) { final TreeViewer viewer = ((FilteredTree)topControl).getViewer(); if (viewer != null) { topTree = viewer.getTree(); } } if (topTree == null) { return; } boolean selectionIsForVisibleViewer = false; final Object src = event.getSource(); if (src instanceof Viewer) { final Control viewerControl = ((Viewer)src).getControl(); if (viewerControl == topTree) { selectionIsForVisibleViewer = true; } } if (!selectionIsForVisibleViewer) { return; } fSelection = event.getSelection(); validate(); } protected void validate() { Button ok_button = getButton(IDialogConstants.OK_ID); boolean isValid = true; if (getSelectedLaunchConfigurations().length < 1) { setErrorMessage(LaunchMessages.MultiLaunchConfigurationSelectionDialog_7); isValid = false; } else { setErrorMessage(null); } if (isValid) { if (fForEditing) { // must have only one selection if (getSelectedLaunchConfigurations().length > 1) { setErrorMessage(LaunchMessages.MultiLaunchConfigurationSelectionDialog_11); isValid = false; } } } if (isValid) { if (action == EPostLaunchAction.DELAY) { isValid = (actionParam instanceof Integer) && ((Integer)actionParam > 0); setErrorMessage(isValid ? null : LaunchMessages.MultiLaunchConfigurationSelectionDialog_10); } } if (ok_button != null) ok_button.setEnabled(isValid); } public void setInitialSelection(LaunchElement el) { action = el.action; actionParam = el.actionParam; isDefaultMode = el.mode.equals(MultiLaunchConfigurationDelegate.DEFAULT_MODE); fInitialSelection = new StructuredSelection(el.data); fSelection = fInitialSelection; } }