/******************************************************************************* * Copyright (c) 2005 Vlad Dumitrescu 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: * Vlad Dumitrescu * Jakob C *******************************************************************************/ package org.erlide.ui.launch; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.ListViewer; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; 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.Group; import org.eclipse.swt.widgets.Shell; import org.erlide.backend.api.BackendData; import org.erlide.backend.api.ErlRuntimeAttributes; import org.erlide.debug.ui.utils.ModuleItemLabelProvider; import org.erlide.debug.ui.views.InterpretedModuleListContentProvider; import org.erlide.engine.ErlangEngine; import org.erlide.engine.model.IErlElement; import org.erlide.engine.model.root.IErlModel; import org.erlide.engine.model.root.IErlModule; import org.erlide.runtime.api.ErlDebugFlags; import org.erlide.ui.dialogs.AddInterpretedModulesSelectionDialog; import org.erlide.ui.util.SWTUtil; import com.google.common.collect.Lists; /** * A tab in the Launch Config with erlang debugger parameters: the debug flags * for attaching and distruibuted debugging a checkbox tree of modules to * interpret upon launching. The checkbox tree classes are reused by * InterpretedModulesView * */ public class DebugTab extends AbstractLaunchConfigurationTab { ListViewer listViewer; private Button attachOnFirstCallCheck; private Button attachOnBreakpointCheck; private Button attachOnExitCheck; private Button distributedDebugCheck; private Button addButton; private Button removeButton; private InterpretedModuleListContentProvider contentProvider; public static class ListLabelProvider extends LabelProvider { @Override public String getText(final Object element) { if (element instanceof IErlElement) { final IErlElement erlElement = (IErlElement) element; return erlElement.getName(); } return "!" + super.getText(element); } @Override public Image getImage(final Object element) { return null; } } /** * @wbp.parser.entryPoint */ @Override public void createControl(final Composite parent) { final Composite comp = new Composite(parent, SWT.NONE); setControl(comp); final GridLayout topLayout = new GridLayout(); comp.setLayout(topLayout); distributedDebugCheck = createCheckButton(comp, "Debug all connected nodes"); final Group attachGroup = SWTUtil.createGroup(comp, "Auto Attach", 1, GridData.FILL_BOTH); attachGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); attachOnFirstCallCheck = createCheckButton(attachGroup, "First &call"); attachOnBreakpointCheck = createCheckButton(attachGroup, "&Breakpoint"); attachOnExitCheck = createCheckButton(attachGroup, "E&xit"); distributedDebugCheck.addSelectionListener(fBasicSelectionListener); attachOnFirstCallCheck.addSelectionListener(fBasicSelectionListener); attachOnBreakpointCheck.addSelectionListener(fBasicSelectionListener); attachOnExitCheck.addSelectionListener(fBasicSelectionListener); final Group interpretedModulesGroup = new Group(comp, SWT.NONE); final GridData gd_interpretedModulesGroup = new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1); gd_interpretedModulesGroup.widthHint = 387; interpretedModulesGroup.setLayoutData(gd_interpretedModulesGroup); interpretedModulesGroup.setText("Interpreted modules"); interpretedModulesGroup.setLayout(new GridLayout(2, false)); // final Label anyModuleHavingLabel = new Label(interpretedModulesGroup, // SWT.WRAP); // anyModuleHavingLabel.setLayoutData(new GridData(279, SWT.DEFAULT)); // anyModuleHavingLabel // .setText("Any module having breakpoints enabled will be dynamically added to // the list.\n\nThis widget is disabled for now, it takes 100%CPU for large // projects. If you need to use \"attach on first call\" or \"attach on exit\", // please mark the modules by setting a dummy breakpoint in them. Sorry for the // inconvenience!"); listViewer = new ListViewer(interpretedModulesGroup, SWT.BORDER | SWT.MULTI); listViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(final SelectionChangedEvent event) { final ISelection selection = event.getSelection(); removeButton.setEnabled(!selection.isEmpty()); } }); // checkboxTreeViewer.addCheckStateListener(new ICheckStateListener() { // @Override // @SuppressWarnings("synthetic-access") // public void checkStateChanged(final CheckStateChangedEvent event) { // final DebugTreeItem dti = (DebugTreeItem) event.getElement(); // checkboxTreeViewer.setGrayed(dti, false); // final boolean checked = event.getChecked(); // setSubtreeChecked(dti, checked); // // checkUpwards(checkboxTreeViewer, dti, checked, false); // updateLaunchConfigurationDialog(); // } // // }); listViewer.setLabelProvider(new ModuleItemLabelProvider()); contentProvider = new InterpretedModuleListContentProvider(); listViewer.setContentProvider(contentProvider); final Control control = listViewer.getControl(); final GridData gd_list = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 3); gd_list.minimumWidth = 250; gd_list.minimumHeight = 120; gd_list.widthHint = 256; gd_list.heightHint = 220; control.setLayoutData(gd_list); addButton = createPushButton(interpretedModulesGroup, "Add...", null); addButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { final List<IErlModule> result = getModulesFromAddModulesDialog( getShell()); contentProvider.addModules(result); listViewer.refresh(); updateLaunchConfigurationDialog(); } }); removeButton = createPushButton(interpretedModulesGroup, "Remove", null); removeButton.setEnabled(false); removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { final IStructuredSelection selection = (IStructuredSelection) listViewer .getSelection(); for (final Object o : selection.toArray()) { contentProvider.removeModule((IErlModule) o); } listViewer.refresh(); updateLaunchConfigurationDialog(); } }); } public static List<IErlModule> getModulesFromAddModulesDialog(final Shell shell) { final List<IErlModule> result = Lists.newArrayList(); final AddInterpretedModulesSelectionDialog dialog = new AddInterpretedModulesSelectionDialog( shell); final int resultCode = dialog.open(); if (resultCode != IDialogConstants.OK_ID) { return result; } final Object[] dialogResult = dialog.getResult(); if (dialogResult == null || dialogResult.length == 0) { return result; } final IErlModel model = ErlangEngine.getInstance().getModel(); for (final Object o : dialogResult) { if (o instanceof IFile) { final IFile file = (IFile) o; result.add(model.findModule(file)); } } return result; } // protected void setSubtreeChecked(final DebugTreeItem dti, // final boolean checked) { // final List<DebugTreeItem> children = dti.getChildren(); // if (children == null || children.size() == 0) { // interpretOrDeinterpret(dti, checked); // return; // } // for (final DebugTreeItem i : children) { // checkboxTreeViewer.setChecked(i, checked); // setSubtreeChecked(i, checked); // } // } // public static void checkUpwards(final CheckboxTreeViewer ctv, // final DebugTreeItem dti, final boolean checked, final boolean grayed) { // for (DebugTreeItem parent = dti.getParent(); parent != null; parent = // parent // .getParent()) { // ctv.setChecked(parent, checked); // } // } @Override public void setDefaults(final ILaunchConfigurationWorkingCopy config) { config.setAttribute(ErlRuntimeAttributes.DEBUG_INTERPRET_MODULES, new ArrayList<String>()); config.setAttribute(ErlRuntimeAttributes.DEBUG_FLAGS, ErlDebugFlags.getFlag(ErlDebugFlags.DEFAULT_DEBUG_FLAGS)); } @Override public void initializeFrom(final ILaunchConfiguration config) { if (listViewer != null) { listViewer.setInput(config); } final Set<String> interpret = BackendData.addBreakpointProjectsAndModules(null, new ArrayList<String>()); contentProvider.addModules(interpret); EnumSet<ErlDebugFlags> debugFlags; try { final int attribute = config.getAttribute(ErlRuntimeAttributes.DEBUG_FLAGS, ErlDebugFlags.getFlag(ErlDebugFlags.DEFAULT_DEBUG_FLAGS)); debugFlags = ErlDebugFlags.makeSet(attribute); } catch (final CoreException e) { debugFlags = ErlDebugFlags.DEFAULT_DEBUG_FLAGS; } setFlagCheckboxes(debugFlags); } @Override public void performApply(final ILaunchConfigurationWorkingCopy config) { config.setAttribute(ErlRuntimeAttributes.DEBUG_FLAGS, ErlDebugFlags.getFlag(getFlagCheckboxes())); final List<String> r = new ArrayList<>(); for (final Object o : contentProvider.getElements(null)) { final IErlModule module = (IErlModule) o; r.add(ErlangEngine.getInstance().getModelUtilService().getProject(module) .getName() + ":" + module.getName()); } config.setAttribute(ErlRuntimeAttributes.DEBUG_INTERPRET_MODULES, r); } @Override public String getName() { return "Debug"; } @Override public boolean isValid(final ILaunchConfiguration config) { return true; } /** * check or uncheck the four flag checkboxes * * @param debugFlags * flags */ private void setFlagCheckboxes(final EnumSet<ErlDebugFlags> debugFlags) { if (attachOnFirstCallCheck == null) { // I don't know why these are null sometimes... return; } attachOnFirstCallCheck .setSelection(debugFlags.contains(ErlDebugFlags.ATTACH_ON_FIRST_CALL)); attachOnBreakpointCheck .setSelection(debugFlags.contains(ErlDebugFlags.ATTACH_ON_BREAKPOINT)); attachOnExitCheck.setSelection(debugFlags.contains(ErlDebugFlags.ATTACH_ON_EXIT)); distributedDebugCheck .setSelection(debugFlags.contains(ErlDebugFlags.DISTRIBUTED_DEBUG)); } /** * get flag settings by reading checkboxes * * @return flags as int */ private EnumSet<ErlDebugFlags> getFlagCheckboxes() { final EnumSet<ErlDebugFlags> result = EnumSet.noneOf(ErlDebugFlags.class); if (attachOnFirstCallCheck.getSelection()) { result.add(ErlDebugFlags.ATTACH_ON_FIRST_CALL); } if (attachOnBreakpointCheck.getSelection()) { result.add(ErlDebugFlags.ATTACH_ON_BREAKPOINT); } if (attachOnExitCheck.getSelection()) { result.add(ErlDebugFlags.ATTACH_ON_EXIT); } if (distributedDebugCheck.getSelection()) { result.add(ErlDebugFlags.DISTRIBUTED_DEBUG); } return result; } private final SelectionListener fBasicSelectionListener = new SelectionListener() { @Override public void widgetDefaultSelected(final SelectionEvent e) { updateLaunchConfigurationDialog(); } @Override public void widgetSelected(final SelectionEvent e) { updateLaunchConfigurationDialog(); } }; }