| /******************************************************************************* |
| * Copyright (c) 2003, 2007 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 |
| * QNX Software Systems - Mikhail Khodjaiants - Bug 89748 |
| *******************************************************************************/ |
| package org.eclipse.debug.internal.ui.sourcelookup; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; |
| import org.eclipse.debug.core.model.ISourceLocator; |
| import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector; |
| import org.eclipse.debug.core.sourcelookup.ISourceContainer; |
| import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector; |
| import org.eclipse.debug.core.sourcelookup.containers.DefaultSourceContainer; |
| import org.eclipse.debug.internal.ui.DebugUIPlugin; |
| import org.eclipse.debug.internal.ui.SWTFactory; |
| import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; |
| import org.eclipse.debug.ui.sourcelookup.WorkingSetSourceContainer; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.ui.IWorkingSet; |
| import org.eclipse.ui.IWorkingSetManager; |
| |
| /** |
| * The panel that contains the list of source containers. |
| * |
| * @since 3.0 |
| */ |
| public class SourceLookupPanel extends AbstractLaunchConfigurationTab implements IPropertyChangeListener { |
| //the configuration being edited |
| protected ILaunchConfiguration fConfig; |
| //the viewer displaying the containers |
| protected SourceContainerViewer fPathViewer; |
| //the duplicates checkbox |
| protected Button fDuplicatesButton; |
| //the source actions - up, down, add, remove, restore |
| protected List<SourceContainerAction> fActions = new ArrayList<>(6); |
| //the director that will be used by the tab to manage/store the containers |
| protected ISourceLookupDirector fLocator; |
| |
| protected AddContainerAction fAddAction; |
| protected EditContainerAction fEditAction; |
| protected RestoreDefaultAction fRestoreDefaultAction; |
| |
| /** |
| * Creates and returns the source lookup control. |
| * |
| * @param parent the parent widget of this control |
| */ |
| @Override |
| public void createControl(Composite parent) { |
| Font font = parent.getFont(); |
| Composite comp = SWTFactory.createComposite(parent, 2, 1, GridData.FILL_BOTH); |
| SWTFactory.createLabel(comp, SourceLookupUIMessages.sourceTab_lookupLabel, 2); |
| |
| fPathViewer = new SourceContainerViewer(comp, this); |
| fPathViewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH)); |
| fPathViewer.getControl().setFont(font); |
| |
| Composite pathButtonComp = SWTFactory.createComposite(comp, comp.getFont(), 1, 1, GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_FILL, 0, 0); |
| |
| SWTFactory.createVerticalSpacer(comp, 2); |
| |
| fDuplicatesButton = SWTFactory.createCheckButton(comp, SourceLookupUIMessages.sourceTab_searchDuplicateLabel, null, false, 2); |
| fDuplicatesButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent evt) { |
| setDirty(true); |
| updateLaunchConfigurationDialog(); |
| } |
| }); |
| |
| fAddAction = new AddContainerAction(); |
| Button button = SWTFactory.createPushButton(pathButtonComp, fAddAction.getText(), null); |
| fAddAction.setButton(button); |
| addAction(fAddAction); |
| |
| fEditAction = new EditContainerAction(); |
| button = SWTFactory.createPushButton(pathButtonComp, fEditAction.getText(), null); |
| fEditAction.setButton(button); |
| addAction(fEditAction); |
| |
| SourceContainerAction action = new RemoveAction(); |
| button = SWTFactory.createPushButton(pathButtonComp, action.getText(), null); |
| action.setButton(button); |
| addAction(action); |
| |
| action = new UpAction(); |
| button = SWTFactory.createPushButton(pathButtonComp, action.getText(), null); |
| action.setButton(button); |
| addAction(action); |
| |
| action = new DownAction(); |
| button = SWTFactory.createPushButton(pathButtonComp, action.getText(), null); |
| action.setButton(button); |
| addAction(action); |
| |
| fRestoreDefaultAction = new RestoreDefaultAction(); |
| button = SWTFactory.createPushButton(pathButtonComp, fRestoreDefaultAction.getText(), null); |
| fRestoreDefaultAction.setButton(button); |
| addAction(fRestoreDefaultAction); |
| |
| retargetActions(fPathViewer); |
| |
| //listen to changes user made to the working sets, if a working set is being removed |
| //check current list to validate working sets |
| IWorkingSetManager workingSetMgr = DebugUIPlugin.getDefault().getWorkbench().getWorkingSetManager(); |
| workingSetMgr.addPropertyChangeListener(this); |
| /*Dialog.applyDialogFont(comp);*/ |
| setControl(comp); |
| } |
| |
| /** |
| * Adds the given action to the action collection in this tab |
| */ |
| protected void addAction(SourceContainerAction action) { |
| fActions.add(action); |
| } |
| |
| /** |
| * Re-targets actions to the given viewer |
| */ |
| protected void retargetActions(SourceContainerViewer viewer) { |
| for (SourceContainerAction action : fActions) { |
| action.setViewer(viewer); |
| } |
| } |
| |
| /** |
| * Initializes this control based on the settings in the given |
| * launch configuration. |
| */ |
| @Override |
| public void initializeFrom(ILaunchConfiguration configuration) { |
| if (fLocator != null) { |
| fLocator.dispose(); |
| fLocator = null; |
| } |
| setErrorMessage(null); |
| setMessage(null); |
| String memento = null; |
| String type = null; |
| try{ |
| memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String)null); |
| type = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String)null); |
| if (type == null) { |
| type = configuration.getType().getSourceLocatorId(); |
| } |
| } catch(CoreException e){ |
| setErrorMessage(e.getMessage()); |
| return; |
| } |
| |
| if(type == null) { |
| setErrorMessage(SourceLookupUIMessages.sourceLookupPanel_2); |
| return; |
| } |
| |
| boolean migration = false; |
| try { |
| ISourceLocator locator = getLaunchManager().newSourceLocator(type); |
| if(!(locator instanceof AbstractSourceLookupDirector)) { |
| // migrate to the new source lookup infrastructure |
| memento = null; // don't use old memento |
| type = configuration.getType().getSourceLocatorId(); |
| if(type == null) { |
| setErrorMessage(SourceLookupUIMessages.sourceLookupPanel_2); |
| return; |
| } |
| locator = getLaunchManager().newSourceLocator(type); |
| if (!(locator instanceof AbstractSourceLookupDirector)) { |
| setErrorMessage(SourceLookupUIMessages.sourceLookupPanel_2); |
| return; |
| } |
| migration = true; |
| } |
| fLocator = (AbstractSourceLookupDirector)locator; |
| if (memento == null) { |
| fLocator.initializeDefaults(configuration); |
| } else { |
| fLocator.initializeFromMemento(memento, configuration); |
| } |
| } catch (CoreException e) { |
| setErrorMessage(e.getMessage()); |
| return; |
| } |
| initializeFrom(fLocator); |
| if (migration && configuration.isWorkingCopy()) { |
| // ensure perform apply actual updates the config |
| setDirty(true); |
| performApply((ILaunchConfigurationWorkingCopy)configuration); |
| } |
| } |
| |
| /** |
| * Initializes this control based on the settings in the given |
| * AbstractSourceLookupDirector |
| */ |
| public void initializeFrom(ISourceLookupDirector locator) { |
| if(fConfig == null) { |
| fConfig = locator.getLaunchConfiguration(); |
| } |
| fPathViewer.setEntries(locator.getSourceContainers()); |
| fDuplicatesButton.setSelection(locator.isFindDuplicates()); |
| fLocator = locator; |
| fAddAction.setSourceLookupDirector(locator); |
| fEditAction.setSourceLookupDirector(locator); |
| fRestoreDefaultAction.setSourceLookupDirector(locator); |
| setDirty(false); |
| } |
| |
| /** |
| * Saves the containers and duplicate policy into the given working copy of the configuration. |
| * Saving the configuration will result in a change event, which will be picked up by the director |
| * and used to refresh its internal list. |
| * |
| * @param workingCopy the working copy of the configuration that these values should be stored in, may be null. |
| * If null, will be written into a working copy of the configuration referenced by the director. |
| */ |
| @Override |
| public void performApply(ILaunchConfigurationWorkingCopy configuration) { |
| if (isDirty()) { |
| if (fLocator == null) { |
| configuration.setAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String)null); |
| configuration.setAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String)null); |
| return; |
| } |
| ILaunchConfigurationWorkingCopy workingCopy = configuration; |
| if(configuration == null) { |
| try { |
| ILaunchConfiguration config = fLocator.getLaunchConfiguration(); |
| if(config != null) { |
| workingCopy = config.getWorkingCopy(); |
| } |
| } |
| catch(CoreException e) { |
| DebugUIPlugin.log(e); |
| setErrorMessage(SourceLookupUIMessages.sourceLookupPanel_1); |
| return; |
| } |
| } |
| if(workingCopy == null) { |
| DebugUIPlugin.logErrorMessage("Error occurred - a working copy could not be acquired, therefore source lookup path changes will not be applied."); //$NON-NLS-1$ |
| return; |
| } |
| //set new values in director so memento returned is correct |
| fLocator.setSourceContainers(fPathViewer.getEntries()); |
| fLocator.setFindDuplicates(fDuplicatesButton.getSelection()); |
| |
| //writing to the file will cause a change event and the listeners will be updated |
| try { |
| if (isDefault()) { |
| workingCopy.setAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String)null); |
| workingCopy.setAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String)null); |
| } else { |
| workingCopy.setAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, fLocator.getMemento()); |
| workingCopy.setAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, fLocator.getId()); |
| } |
| } |
| catch(CoreException e) { |
| DebugUIPlugin.log(e); |
| setErrorMessage(SourceLookupUIMessages.sourceLookupPanel_1); |
| } |
| |
| } |
| } |
| |
| /** |
| * determines of the current source lookup path is the default path |
| * @param configuration |
| * @return |
| */ |
| protected boolean isDefault() { |
| ISourceContainer[] current = getEntries(); |
| return !fDuplicatesButton.getSelection() && current.length == 1 && current[0] instanceof DefaultSourceContainer; |
| } |
| |
| /** |
| * Returns the entries visible in the viewer |
| */ |
| public ISourceContainer[] getEntries() { |
| return fPathViewer.getEntries(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#setDirty(boolean) |
| */ |
| @Override |
| public void setDirty(boolean dirty) { |
| super.setDirty(dirty); |
| |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName() |
| */ |
| @Override |
| public String getName() { |
| return SourceLookupUIMessages.sourceTab_tabTitle; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) |
| */ |
| @Override |
| public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {} |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#updateLaunchConfigurationDialog() |
| */ |
| @Override |
| protected void updateLaunchConfigurationDialog() { |
| if (getLaunchConfigurationDialog() != null) { |
| super.updateLaunchConfigurationDialog(); |
| } |
| } |
| |
| /** |
| * This is called whenever a working set has been removed. Loops through the original list |
| * of working sets the user stores in the configuration. If the one being removed is in the |
| * list, remove it from the list |
| * @param affectedWorkingSet - the working set being removed |
| */ |
| private void validateWorkingSetSourceContainers(IWorkingSet affectedWorkingSet) { |
| List<?> sourceContainers = (List<?>) fPathViewer.getInput(); |
| if (sourceContainers != null) { |
| for (int i = 0; i < sourceContainers.size(); i++) { |
| if (sourceContainers.get(i) instanceof WorkingSetSourceContainer) { |
| WorkingSetSourceContainer wsSrcContainer = (WorkingSetSourceContainer) sourceContainers.get(i); |
| if (wsSrcContainer.getName().equals(affectedWorkingSet.getName())) { |
| sourceContainers.remove(i); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Listen to working set changes |
| * @param event |
| */ |
| @Override |
| public void propertyChange(PropertyChangeEvent event) { |
| //if the PropertyChangeEvent has changeId CHANGE_WORKING_SET_REMOVE, |
| //validate the list to make sure all working sets are valid |
| //if the PropertyChangeEvent has changeId CHANGE_WORKING_SET_NAME_CHANGE, |
| //do nothing because the event only has newValue, since oldValue is not provided |
| //there is no way to identify which working set does the newValue corresponds to |
| if (event.getProperty().equals(IWorkingSetManager.CHANGE_WORKING_SET_REMOVE)) { |
| validateWorkingSetSourceContainers((IWorkingSet) event.getOldValue()); |
| } |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.ILaunchConfigurationTab#activated(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) |
| */ |
| @Override |
| public void activated(ILaunchConfigurationWorkingCopy workingCopy) { |
| initializeFrom(workingCopy); |
| } |
| |
| /** |
| * Returns the source lookup director associated with this |
| * panel, or <code>null</code> if none. |
| * |
| * @return the source lookup director associated with this |
| * panel, or <code>null</code> if none |
| */ |
| public ISourceLookupDirector getDirector() { |
| return fLocator; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.ILaunchConfigurationTab#dispose() |
| */ |
| @Override |
| public void dispose() { |
| super.dispose(); |
| //listen to changes user made to the working sets, if a working set is being removed |
| //check current list to validate working sets |
| IWorkingSetManager workingSetMgr = DebugUIPlugin.getDefault().getWorkbench().getWorkingSetManager(); |
| workingSetMgr.removePropertyChangeListener(this); |
| } |
| } |