| /******************************************************************************* |
| * Copyright (c) 2006, 2017 IBM Corporation 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: |
| * IBM Corporation - initial API and implementation |
| * Lars Vogel <Lars.Vogel@vogella.com> - Bug 490755 |
| *******************************************************************************/ |
| package org.eclipse.debug.internal.ui.preferences; |
| |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.ILaunchConfigurationType; |
| import org.eclipse.debug.core.ILaunchDelegate; |
| import org.eclipse.debug.internal.core.IInternalDebugCoreConstants; |
| import org.eclipse.debug.internal.core.LaunchManager; |
| import org.eclipse.debug.internal.ui.DebugUIPlugin; |
| import org.eclipse.debug.internal.ui.DefaultLabelProvider; |
| import org.eclipse.debug.internal.ui.IDebugHelpContextIds; |
| import org.eclipse.debug.internal.ui.SWTFactory; |
| import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationPresentationManager; |
| import org.eclipse.jface.preference.PreferencePage; |
| import org.eclipse.jface.viewers.ArrayContentProvider; |
| import org.eclipse.jface.viewers.CheckStateChangedEvent; |
| import org.eclipse.jface.viewers.CheckboxTableViewer; |
| import org.eclipse.jface.viewers.ICheckStateListener; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.ITreeContentProvider; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.TreeViewer; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Group; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Table; |
| import org.eclipse.swt.widgets.Tree; |
| import org.eclipse.ui.IWorkbench; |
| import org.eclipse.ui.IWorkbenchPreferencePage; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.model.WorkbenchViewerComparator; |
| |
| /** |
| * This class provides a preference page for selecting and changing preferred launch delegates for those of them |
| * that have conflicting delegates. |
| * |
| * Delegates are considered to be conflicting if they are for the same launch configuration type, and apply to the same |
| * mode sets. |
| * |
| * @since 3.3 |
| */ |
| public class LaunchersPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { |
| |
| /** |
| * Class to collect and persist attributes to sufficiently describe a duplicate launch delegate |
| */ |
| class DuplicateDelegate { |
| private ILaunchConfigurationType fType = null; |
| private ILaunchDelegate[] fDelegates = null; |
| private Set<String> fModes = null; |
| |
| public DuplicateDelegate(ILaunchConfigurationType type, ILaunchDelegate[] delegates, Set<String> modes) { |
| fModes = modes; |
| fType = type; |
| fDelegates = delegates; |
| } |
| |
| public ILaunchConfigurationType getType() { |
| return fType; |
| } |
| public ILaunchDelegate[] getDelegates() { |
| return fDelegates; |
| } |
| |
| public Set<String> getModeSet() { |
| return fModes; |
| } |
| } |
| |
| /** |
| * label provider to extend the default one, provides labels to both the tree and table of this page |
| */ |
| class LabelProvider extends DefaultLabelProvider { |
| @Override |
| public String getText(Object element) { |
| if(element instanceof ILaunchConfigurationType) { |
| return super.getText(element); |
| } |
| else if(element instanceof DuplicateDelegate) { |
| DuplicateDelegate dd = (DuplicateDelegate) element; |
| return LaunchConfigurationPresentationManager.getDefault().getLaunchModeNames(dd.getModeSet()).toString(); |
| } |
| else if(element instanceof ILaunchDelegate){ |
| return ((ILaunchDelegate) element).getName(); |
| } |
| return element.toString(); |
| } |
| } |
| |
| /** |
| * This class is used to provide content to the tree |
| */ |
| class TreeProvider implements ITreeContentProvider { |
| @Override |
| public Object[] getChildren(Object parentElement) { |
| if(parentElement instanceof ILaunchConfigurationType) { |
| ILaunchConfigurationType type = (ILaunchConfigurationType) parentElement; |
| Set<DuplicateDelegate> dupes = fDuplicates.get(type); |
| if(dupes != null) { |
| return dupes.toArray(); |
| } |
| return null; |
| } |
| return null; |
| } |
| @Override |
| public boolean hasChildren(Object element) { |
| return element instanceof ILaunchConfigurationType; |
| } |
| @Override |
| public Object[] getElements(Object inputElement) { |
| if(inputElement instanceof Map) { |
| return ((Map<?, ?>) inputElement).keySet().toArray(); |
| } |
| return null; |
| } |
| @Override |
| public Object getParent(Object element) {return null;} |
| } |
| |
| private TreeViewer fTreeViewer = null; |
| private CheckboxTableViewer fTableViewer = null; |
| private Map<ILaunchConfigurationType, Set<DuplicateDelegate>> fDuplicates = null; |
| private Map<DuplicateDelegate, ILaunchDelegate> fDupeSelections = null; |
| private boolean fDirty = false; |
| private Label fDescription = null; |
| |
| /** |
| * Constructor |
| */ |
| public LaunchersPreferencePage() { |
| setTitle(DebugPreferencesMessages.LaunchDelegatesPreferencePage_0); |
| } |
| |
| @Override |
| public void createControl(Composite parent) { |
| super.createControl(parent); |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IDebugHelpContextIds.LAUNCH_DELEGATES_PREFERENCE_PAGE); |
| } |
| |
| @Override |
| protected Control createContents(Composite parent) { |
| Composite comp = SWTFactory.createComposite(parent, 2, 1, GridData.FILL_BOTH); |
| SWTFactory.createWrapLabel(comp, DebugPreferencesMessages.LaunchDelegatesPreferencePage_1, 2, 300); |
| |
| boolean enabled = fDuplicates.size() > 0; |
| if(!enabled) { |
| SWTFactory.createVerticalSpacer(comp, 1); |
| SWTFactory.createWrapLabel(comp, DebugPreferencesMessages.LaunchersPreferencePage_0, 2, 300); |
| } |
| |
| SWTFactory.createVerticalSpacer(comp, 1); |
| //tree |
| Composite comp1 = SWTFactory.createComposite(comp, 1, 1, GridData.FILL_VERTICAL); |
| SWTFactory.createLabel(comp1, DebugPreferencesMessages.LaunchDelegatesPreferencePage_2, 1); |
| Tree tree = new Tree(comp1, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE); |
| tree.setEnabled(enabled); |
| tree.setFont(parent.getFont()); |
| GridData gd = new GridData(GridData.FILL_BOTH); |
| gd.grabExcessHorizontalSpace = false; |
| tree.setLayoutData(gd); |
| fTreeViewer = new TreeViewer(tree); |
| fTreeViewer.setComparator(new WorkbenchViewerComparator()); |
| fTreeViewer.setContentProvider(new TreeProvider()); |
| fTreeViewer.setLabelProvider(new LabelProvider()); |
| fTreeViewer.setInput(fDuplicates); |
| fTreeViewer.expandToLevel(2); |
| fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { |
| @Override |
| public void selectionChanged(SelectionChangedEvent event) { |
| Object obj = ((IStructuredSelection) event.getSelection()).getFirstElement(); |
| if(obj instanceof DuplicateDelegate) { |
| fTableViewer.setAllChecked(false); |
| DuplicateDelegate dd = (DuplicateDelegate) obj; |
| fTableViewer.setInput(dd.getDelegates()); |
| fTableViewer.setSelection(null); |
| obj = fDupeSelections.get(dd); |
| if(obj != null) { |
| fTableViewer.setChecked(obj, true); |
| fTableViewer.setSelection(new StructuredSelection(obj)); |
| } |
| } |
| else { |
| fTableViewer.setInput(null); |
| } |
| } |
| }); |
| |
| //table |
| Composite comp2 = SWTFactory.createComposite(comp, comp.getFont(), 1, 1, GridData.FILL_BOTH); |
| SWTFactory.createLabel(comp2, DebugPreferencesMessages.LaunchDelegatesPreferencePage_3, 1); |
| Table table = new Table(comp2, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CHECK | SWT.SINGLE); |
| table.setEnabled(enabled); |
| table.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| table.setFont(parent.getFont()); |
| fTableViewer = new CheckboxTableViewer(table); |
| fTableViewer.setComparator(new WorkbenchViewerComparator()); |
| fTableViewer.setLabelProvider(new LabelProvider()); |
| fTableViewer.setContentProvider(new ArrayContentProvider()); |
| fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { |
| @Override |
| public void selectionChanged(SelectionChangedEvent event) { |
| IStructuredSelection ss = (IStructuredSelection) event.getSelection(); |
| if(ss != null && !ss.isEmpty()) { |
| ILaunchDelegate delegate = (ILaunchDelegate)ss.getFirstElement(); |
| fDescription.setText(delegate.getDescription()); |
| } |
| else { |
| fDescription.setText(IInternalDebugCoreConstants.EMPTY_STRING); |
| } |
| } |
| }); |
| fTableViewer.addCheckStateListener(new ICheckStateListener() { |
| @Override |
| public void checkStateChanged(CheckStateChangedEvent event) { |
| fDirty = true; |
| Object element = event.getElement(); |
| boolean checked = event.getChecked(); |
| //always set checked, this way users cannot 'undo' a change to selecting a preferred delegate |
| //The story for this is that on startup if there are dupes, the user is prompted to pick a delegate, after that they cannot |
| //return to a state of not being able to launch something, but can pick a different delegate |
| fTableViewer.setCheckedElements(new Object[] {element}); |
| //set the selection to be the checked element |
| //https://bugs.eclipse.org/bugs/show_bug.cgi?id=233233 |
| fTableViewer.setSelection(new StructuredSelection(element)); |
| //persist the selection |
| Object obj = ((IStructuredSelection) fTreeViewer.getSelection()).getFirstElement(); |
| if(obj instanceof DuplicateDelegate) { |
| fDupeSelections.remove(obj); |
| if(checked) { |
| fDupeSelections.put((DuplicateDelegate) obj, (ILaunchDelegate) element); |
| } |
| } |
| } |
| }); |
| Group group = SWTFactory.createGroup(comp, DebugPreferencesMessages.LaunchDelegatesPreferencePage_4, 1, 2, GridData.FILL_BOTH); |
| fDescription = SWTFactory.createWrapLabel(group, "", 1); //$NON-NLS-1$ |
| return comp; |
| } |
| |
| @Override |
| public boolean performOk() { |
| if(fDirty && fDupeSelections != null && fDupeSelections.size() > 0) { |
| fDirty = false; |
| DuplicateDelegate dd = null; |
| ILaunchDelegate delegate = null; |
| for (Iterator<DuplicateDelegate> iter = fDupeSelections.keySet().iterator(); iter.hasNext();) { |
| dd = iter.next(); |
| delegate = fDupeSelections.get(dd); |
| try { |
| dd.getType().setPreferredDelegate(dd.getModeSet(), delegate); |
| } |
| catch (CoreException e) {DebugUIPlugin.log(e);} |
| } |
| } |
| return super.performOk(); |
| } |
| |
| @Override |
| public void init(IWorkbench workbench) { |
| //init a listing of duplicate delegates arranged by type |
| try { |
| setPreferenceStore(DebugUIPlugin.getDefault().getPreferenceStore()); |
| LaunchManager lm = (LaunchManager) DebugPlugin.getDefault().getLaunchManager(); |
| ILaunchConfigurationType[] types = lm.getLaunchConfigurationTypes(); |
| fDuplicates = new HashMap<>(); |
| fDupeSelections = new HashMap<>(); |
| ILaunchDelegate[] delegates = null; |
| Set<Set<String>> modes = null; |
| Set<String> modeset = null; |
| Set<DuplicateDelegate> tmp = null; |
| ILaunchDelegate prefdelegate = null; |
| DuplicateDelegate dd = null; |
| for(int i = 0; i < types.length; i++) { |
| modes = types[i].getSupportedModeCombinations(); |
| for (Iterator<Set<String>> iter = modes.iterator(); iter.hasNext();) { |
| modeset = iter.next(); |
| delegates = types[i].getDelegates(modeset); |
| if(delegates.length > 1) { |
| tmp = fDuplicates.get(types[i]); |
| if(tmp == null) { |
| tmp = new HashSet<>(); |
| } |
| dd = new DuplicateDelegate(types[i], delegates, modeset); |
| tmp.add(dd); |
| fDuplicates.put(types[i], tmp); |
| prefdelegate = types[i].getPreferredDelegate(modeset); |
| if(prefdelegate != null) { |
| fDupeSelections.put(dd, prefdelegate); |
| } |
| } |
| } |
| } |
| } |
| catch(CoreException e) {DebugUIPlugin.log(e);} |
| } |
| |
| } |