blob: 57eab83ccc4b8c0d8395a5761b6a7ab51c6a1bdb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2017 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Code 9 Corporation - ongoing enhancements
* Benjamin Cabe <benjamin.cabe@anyware-tech.com> - bug 262885
* Alena Laskavaia - Bug 453392 - No debug options help
*******************************************************************************/
package org.eclipse.pde.internal.ui.launcher;
import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.*;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.core.plugin.PluginRegistry;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.core.TracingOptionsManager;
import org.eclipse.pde.internal.ui.PDEPlugin;
import org.eclipse.pde.internal.ui.PDEUIMessages;
import org.eclipse.pde.internal.ui.util.SWTUtil;
import org.eclipse.pde.internal.ui.wizards.ListUtil;
import org.eclipse.pde.launching.IPDELauncherConstants;
import org.eclipse.pde.ui.launcher.AbstractLauncherTab;
import org.eclipse.pde.ui.launcher.TracingTab;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledPageBook;
public class TracingBlock {
private TracingTab fTab;
private Button fTracingCheck;
private CheckboxTableViewer fPluginViewer;
private IPluginModelBase[] fTraceableModels;
private Properties fMasterOptions = new Properties();
private Button fSelectAllButton;
private Button fDeselectAllButton;
private Button fRestoreSelectedDefaultButton;
private Button fRestoreDefaultButton;
private Hashtable<IPluginModelBase, TracingPropertySource> fPropertySources = new Hashtable<>();
private FormToolkit fToolkit;
private ScrolledPageBook fPageBook;
/**
* The last selected item in the list is stored in the dialog settings.
*/
private static final String TRACING_SETTINGS = "TracingTab"; //$NON-NLS-1$
private static final String SETTINGS_SELECTED_PLUGIN = "selectedPlugin"; //$NON-NLS-1$
public TracingBlock(TracingTab tab) {
fTab = tab;
}
public AbstractLauncherTab getTab() {
return fTab;
}
public void createControl(Composite parent) {
fTracingCheck = new Button(parent, SWT.CHECK);
fTracingCheck.setText(PDEUIMessages.TracingLauncherTab_tracing);
fTracingCheck.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fTracingCheck.addSelectionListener(widgetSelectedAdapter(e -> {
masterCheckChanged(true);
fTab.updateLaunchConfigurationDialog();
if (fTracingCheck.getSelection()) {
IStructuredSelection selection = fPluginViewer.getStructuredSelection();
if (!selection.isEmpty()) {
pluginSelected((IPluginModelBase) selection.getFirstElement(), fPluginViewer.getChecked(selection.getFirstElement()));
}
}
}));
createSashSection(parent);
}
private void createSashSection(Composite container) {
SashForm sashForm = new SashForm(container, SWT.HORIZONTAL);
sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
createPluginViewer(sashForm);
createPropertySheetClient(sashForm);
}
private void createPluginViewer(Composite sashForm) {
Composite composite = new Composite(sashForm, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
layout.marginWidth = layout.marginHeight = 1;
composite.setLayout(layout);
fPluginViewer = CheckboxTableViewer.newCheckList(composite, SWT.BORDER);
fPluginViewer.setContentProvider(ArrayContentProvider.getInstance());
fPluginViewer.setLabelProvider(PDEPlugin.getDefault().getLabelProvider());
fPluginViewer.setComparator(new ListUtil.PluginComparator());
fPluginViewer.addSelectionChangedListener(e -> {
fRestoreSelectedDefaultButton.setEnabled(true);
CheckboxTableViewer tableViewer = (CheckboxTableViewer) e.getSource();
boolean selected = tableViewer.getChecked(getSelectedModel());
pluginSelected(getSelectedModel(), selected);
storeSelectedModel();
});
fPluginViewer.addCheckStateListener(event -> {
CheckboxTableViewer tableViewer = (CheckboxTableViewer) event.getSource();
tableViewer.setSelection(new StructuredSelection(event.getElement()));
pluginSelected(getSelectedModel(), event.getChecked());
fTab.updateLaunchConfigurationDialog();
});
fPluginViewer.addDoubleClickListener(event -> {
CheckboxTableViewer tableViewer = (CheckboxTableViewer) event.getSource();
Object selection = ((IStructuredSelection) event.getSelection()).getFirstElement();
boolean addingCheck = !tableViewer.getChecked(selection);
tableViewer.setChecked(selection, addingCheck);
pluginSelected(getSelectedModel(), addingCheck);
fTab.updateLaunchConfigurationDialog();
});
GridData gd = new GridData(GridData.FILL_BOTH);
gd.widthHint = 125;
gd.heightHint = 100;
fPluginViewer.getTable().setLayoutData(gd);
createButtonSection(composite);
}
private void createPropertySheetClient(Composite sashForm) {
Composite tableChild = new Composite(sashForm, SWT.NULL);
GridLayout layout = new GridLayout();
layout.marginHeight = layout.marginWidth = 0;
tableChild.setLayout(layout);
int margin = createPropertySheet(tableChild);
layout.marginWidth = layout.marginHeight = margin;
}
private void createButtonSection(Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
container.setLayout(layout);
fSelectAllButton = new Button(container, SWT.PUSH);
fSelectAllButton.setText(PDEUIMessages.TracingLauncherTab_enableAll);
fSelectAllButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
SWTUtil.setButtonDimensionHint(fSelectAllButton);
fSelectAllButton.addSelectionListener(widgetSelectedAdapter(e -> {
fPluginViewer.setAllChecked(true);
pluginSelected(getSelectedModel(), true);
fTab.updateLaunchConfigurationDialog();
}));
fDeselectAllButton = new Button(container, SWT.PUSH);
fDeselectAllButton.setText(PDEUIMessages.TracinglauncherTab_disableAll);
fDeselectAllButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
SWTUtil.setButtonDimensionHint(fDeselectAllButton);
fDeselectAllButton.addSelectionListener(widgetSelectedAdapter(e -> {
fPluginViewer.setAllChecked(false);
pluginSelected(getSelectedModel(), false);
fTab.updateLaunchConfigurationDialog();
}));
}
private void createRestoreButtonSection(Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
container.setLayout(layout);
fRestoreSelectedDefaultButton = new Button(container, SWT.PUSH);
fRestoreSelectedDefaultButton.setText(PDEUIMessages.TracingBlock_restore_default_selected);
fRestoreSelectedDefaultButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
SWTUtil.setButtonDimensionHint(fRestoreSelectedDefaultButton);
fRestoreSelectedDefaultButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
IStructuredSelection selec = fPluginViewer.getStructuredSelection();
if (selec.getFirstElement() instanceof IPluginModelBase) {
IPluginModelBase model = (IPluginModelBase) selec.getFirstElement();
String modelName = model.getBundleDescription().getSymbolicName();
if (modelName != null) {
Properties properties = PDECore.getDefault().getTracingOptionsManager()
.getTracingTemplateCopy();
for (String key : properties.stringPropertyNames()) {
if (key.startsWith(modelName + '/')) {
fMasterOptions.remove(key);
fMasterOptions.put(key, properties.getProperty(key));
TracingPropertySource source = getPropertySource(model);
source.setChanged(true);
}
}
pluginSelected(model, fPluginViewer.getChecked(model));
}
}
}
});
fRestoreDefaultButton = new Button(container, SWT.PUSH);
fRestoreDefaultButton.setText(PDEUIMessages.TracingBlock_restore_default);
fRestoreDefaultButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
SWTUtil.setButtonDimensionHint(fRestoreDefaultButton);
fRestoreDefaultButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
disposePropertySources();
fMasterOptions.clear();
fMasterOptions.putAll(PDECore.getDefault().getTracingOptionsManager().getTracingTemplateCopy());
Object elements[] = fPluginViewer.getCheckedElements();
for (int i = 0; i < elements.length; i++) {
if (elements[i] instanceof IPluginModelBase) {
IPluginModelBase model = (IPluginModelBase) (elements[i]);
TracingPropertySource source = getPropertySource(model);
PageBookKey key = new PageBookKey(model, true);
Composite parent = fPageBook.createPage(key);
source.createContents(parent, true);
source.setChanged(false);
}
}
IStructuredSelection selec = fPluginViewer.getStructuredSelection();
if (selec.getFirstElement() instanceof IPluginModelBase) {
IPluginModelBase model = (IPluginModelBase) fPluginViewer.getStructuredSelection().getFirstElement();
pluginSelected(model, fPluginViewer.getChecked(model));
}
}
});
}
protected int createPropertySheet(Composite parent) {
fToolkit = new FormToolkit(parent.getDisplay());
int toolkitBorderStyle = fToolkit.getBorderStyle();
int style = toolkitBorderStyle == SWT.BORDER ? SWT.NULL : SWT.BORDER;
Composite container = new Composite(parent, style);
FillLayout flayout = new FillLayout();
flayout.marginWidth = 1;
flayout.marginHeight = 1;
container.setLayout(flayout);
container.setLayoutData(new GridData(GridData.FILL_BOTH));
fPageBook = new ScrolledPageBook(container, style | SWT.V_SCROLL | SWT.H_SCROLL);
fToolkit.adapt(fPageBook, false, false);
createRestoreButtonSection(parent);
if (style == SWT.NULL) {
fPageBook.setData(FormToolkit.KEY_DRAW_BORDER, FormToolkit.TREE_BORDER);
fToolkit.paintBordersFor(container);
}
return style == SWT.NULL ? 2 : 0;
}
public void initializeFrom(ILaunchConfiguration config) {
fMasterOptions.clear();
disposePropertySources();
try {
fTracingCheck.setSelection(config.getAttribute(IPDELauncherConstants.TRACING, false));
Map<String, String> options = config.getAttribute(IPDELauncherConstants.TRACING_OPTIONS, (Map<String, String>) null);
if (options == null) {
fMasterOptions.putAll(PDECore.getDefault().getTracingOptionsManager().getTracingTemplateCopy());
} else {
fMasterOptions.putAll(PDECore.getDefault().getTracingOptionsManager().getTracingOptions(options));
}
masterCheckChanged(false);
String checked = config.getAttribute(IPDELauncherConstants.TRACING_CHECKED, (String) null);
if (checked == null) {
fPluginViewer.setAllChecked(true);
} else if (checked.equals(IPDELauncherConstants.TRACING_NONE)) {
fPluginViewer.setAllChecked(false);
} else {
StringTokenizer tokenizer = new StringTokenizer(checked, ","); //$NON-NLS-1$
ArrayList<IPluginModelBase> list = new ArrayList<>();
while (tokenizer.hasMoreTokens()) {
String id = tokenizer.nextToken();
IPluginModelBase model = PluginRegistry.findModel(id);
model = PluginRegistry.findModel(id);
if (model != null) {
list.add(model);
}
}
fPluginViewer.setCheckedElements(list.toArray());
IPluginModelBase model = getLastSelectedPlugin();
if (model == null && !list.isEmpty()) {
model = list.get(0);
}
if (model != null) {
fPluginViewer.setSelection(new StructuredSelection(model), true);
if (fTracingCheck.getSelection()) {
pluginSelected(model, list.contains(model));
}
} else {
pluginSelected(null, false);
}
}
} catch (CoreException e) {
PDEPlugin.logException(e);
}
}
public void performApply(ILaunchConfigurationWorkingCopy config) {
boolean tracingEnabled = fTracingCheck.getSelection();
config.setAttribute(IPDELauncherConstants.TRACING, tracingEnabled);
if (tracingEnabled) {
boolean changes = false;
for (Enumeration<TracingPropertySource> elements = fPropertySources.elements(); elements.hasMoreElements();) {
TracingPropertySource source = elements.nextElement();
if (source.isModified()) {
changes = true;
source.save();
}
}
if (changes) {
HashMap<String, String> atts = new HashMap<>(fMasterOptions.size());
for (Entry<Object, Object> entry : fMasterOptions.entrySet()) {
String key = (String) entry.getKey();
// these are comment keys which we don't want to save
if (!key.startsWith("#")) //$NON-NLS-1$
atts.put(key, (String) entry.getValue());
}
config.setAttribute(IPDELauncherConstants.TRACING_OPTIONS, atts);
}
}
Object[] checked = fPluginViewer.getCheckedElements();
if (checked.length == 0) {
config.setAttribute(IPDELauncherConstants.TRACING_CHECKED, IPDELauncherConstants.TRACING_NONE);
} else if (checked.length == fPluginViewer.getTable().getItemCount()) {
config.setAttribute(IPDELauncherConstants.TRACING_CHECKED, (String) null);
} else {
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < checked.length; i++) {
IPluginModelBase model = (IPluginModelBase) checked[i];
buffer.append(model.getPluginBase().getId());
if (i < checked.length - 1)
buffer.append(',');
}
config.setAttribute(IPDELauncherConstants.TRACING_CHECKED, buffer.toString());
}
}
public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
configuration.setAttribute(IPDELauncherConstants.TRACING, false);
configuration.setAttribute(IPDELauncherConstants.TRACING_CHECKED, IPDELauncherConstants.TRACING_NONE);
}
public void activated(ILaunchConfigurationWorkingCopy workingCopy) {
fPageBook.getParent().getParent().layout(true);
}
public void dispose() {
if (fToolkit != null)
fToolkit.dispose();
}
public FormToolkit getToolkit() {
return fToolkit;
}
private IPluginModelBase getSelectedModel() {
if (fTracingCheck.isEnabled()) {
Object item = fPluginViewer.getStructuredSelection().getFirstElement();
if (item instanceof IPluginModelBase)
return ((IPluginModelBase) item);
}
return null;
}
private void pluginSelected(IPluginModelBase model, boolean checked) {
TracingPropertySource source = getPropertySource(model);
if (source == null) {
fPageBook.showEmptyPage();
} else {
PageBookKey key = new PageBookKey(model, checked);
if (!fPageBook.hasPage(key) || source.isChanged()) {
Composite parent = fPageBook.createPage(key);
source.createContents(parent, checked);
source.setChanged(false);
}
fPageBook.showPage(key);
}
}
private IPluginModelBase[] getTraceableModels() {
if (fTraceableModels == null) {
IPluginModelBase[] models = PluginRegistry.getActiveModels();
ArrayList<IPluginModelBase> result = new ArrayList<>();
for (IPluginModelBase model : models) {
if (TracingOptionsManager.isTraceable(model))
result.add(model);
}
fTraceableModels = result.toArray(new IPluginModelBase[result.size()]);
}
return fTraceableModels;
}
/**
* Returns the last selected plug-in as stored in dialog settings or <code>null</code> if no
* previous selection is found.
*
* @return model for the last selected plug-in or <code>null</code>
*/
private IPluginModelBase getLastSelectedPlugin() {
IDialogSettings settings = PDEPlugin.getDefault().getDialogSettings().getSection(TRACING_SETTINGS);
if (settings != null) {
String id = settings.get(SETTINGS_SELECTED_PLUGIN);
if (id != null && id.trim().length() > 0) {
return PluginRegistry.findModel(id);
}
}
return null;
}
/**
* Stores the currently selected model in the dialog settings for later retrieval using
* {@link #getLastSelectedPlugin()}. If no model is selected, the settings are cleared.
*/
private void storeSelectedModel() {
IDialogSettings settings = PDEPlugin.getDefault().getDialogSettings().getSection(TRACING_SETTINGS);
if (settings == null) {
settings = PDEPlugin.getDefault().getDialogSettings().addNewSection(TRACING_SETTINGS);
}
IPluginModelBase model = getSelectedModel();
if (model != null && fPluginViewer.getChecked(model)) {
settings.put(SETTINGS_SELECTED_PLUGIN, model.getPluginBase().getId());
} else {
settings.put(SETTINGS_SELECTED_PLUGIN, (String) null);
}
}
private TracingPropertySource getPropertySource(IPluginModelBase model) {
if (model == null)
return null;
TracingPropertySource source = fPropertySources.get(model);
if (source == null) {
String id = model.getPluginBase().getId();
Hashtable<String, String> defaults = PDECore.getDefault().getTracingOptionsManager().getTemplateTable(id);
source = new TracingPropertySource(model, fMasterOptions, defaults, this);
fPropertySources.put(model, source);
source.setChanged(true);
}
return source;
}
private void masterCheckChanged(boolean userChange) {
boolean enabled = fTracingCheck.getSelection();
fPluginViewer.getTable().setEnabled(enabled);
Control currentPage = fPageBook.getCurrentPage();
if (currentPage != null && enabled == false) {
fPageBook.showEmptyPage();
}
if (enabled) {
fPluginViewer.setInput(getTraceableModels());
}
int count = 0;
if(fPluginViewer!=null)
count = fPluginViewer.getTable().getItemCount();
fSelectAllButton.setEnabled(enabled && count > 0);
fDeselectAllButton.setEnabled(enabled && count > 0);
fRestoreDefaultButton.setEnabled(enabled && count > 0);
fRestoreSelectedDefaultButton.setEnabled(!fPluginViewer.getStructuredSelection().isEmpty());
if (enabled == false) {
fRestoreSelectedDefaultButton.setEnabled(false);
}
}
private void disposePropertySources() {
Enumeration<TracingPropertySource> elements = fPropertySources.elements();
while (elements.hasMoreElements()) {
TracingPropertySource source = elements.nextElement();
fPageBook.removePage(source.getModel());
}
fPropertySources.clear();
}
private static class PageBookKey {
IPluginModelBase fModel;
boolean fEnabled;
PageBookKey(IPluginModelBase model, boolean enabled) {
fModel = model;
fEnabled = enabled;
}
@Override
public boolean equals(Object object) {
if (object instanceof PageBookKey) {
return fEnabled == ((PageBookKey) object).fEnabled && fModel.equals(((PageBookKey) object).fModel);
}
return false;
}
@Override
public int hashCode() {
return fModel.hashCode() + (fEnabled ? 1 : 0);
}
}
}