blob: f0c71ba84f6dfc5429db1015c984939dffb260db [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2018 IBM Corporation and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
*******************************************************************************/
package org.eclipse.dltk.internal.ui.workingsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Shell;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.IWorkingSetEditWizard;
import org.eclipse.ui.dialogs.IWorkingSetNewWizard;
import org.eclipse.ui.dialogs.SelectionDialog;
public class WorkingSetConfigurationDialog extends SelectionDialog {
private static class WorkingSetLabelProvider extends LabelProvider {
private Map fIcons;
public WorkingSetLabelProvider() {
fIcons = new Hashtable();
}
@Override
public void dispose() {
Iterator iterator = fIcons.values().iterator();
while (iterator.hasNext()) {
Image icon = (Image) iterator.next();
icon.dispose();
}
super.dispose();
}
@Override
public Image getImage(Object object) {
Assert.isTrue(object instanceof IWorkingSet);
IWorkingSet workingSet = (IWorkingSet) object;
ImageDescriptor imageDescriptor = workingSet.getImageDescriptor();
if (imageDescriptor == null)
return null;
Image icon = (Image) fIcons.get(imageDescriptor);
if (icon == null) {
icon = imageDescriptor.createImage();
fIcons.put(imageDescriptor, icon);
}
return icon;
}
@Override
public String getText(Object object) {
Assert.isTrue(object instanceof IWorkingSet);
IWorkingSet workingSet = (IWorkingSet) object;
return workingSet.getName();
}
}
private class Filter extends ViewerFilter {
@Override
public boolean select(Viewer viewer, Object parentElement,
Object element) {
IWorkingSet ws = (IWorkingSet) element;
String id = ws.getId();
return WorkingSetIDs.OTHERS.equals(id)
|| WorkingSetIDs.SCRIPT.equals(id)
|| WorkingSetIDs.RESOURCE.equals(id) || isCompatible(ws)
|| isActive(ws);
}
private boolean isCompatible(IWorkingSet set) {
if (!set.isSelfUpdating() || set.isAggregateWorkingSet())
return false;
IAdaptable[] elements = set.getElements();
if (elements.length == 0)
return false;
for (int i = 0; i < elements.length; i++) {
IAdaptable element = elements[i];
IProject p = element.getAdapter(IProject.class);
if (p == null || p.exists())
return true;
}
return false;
}
private boolean isActive(IWorkingSet workingSet) {
return fActiveWorkingSets.contains(workingSet);
}
}
private List fAllWorkingSets;
private List fActiveWorkingSets;
private CheckboxTableViewer fTableViewer;
private Button fNewButton;
private Button fEditButton;
private Button fRemoveButton;
private Button fUpButton;
private Button fDownButton;
private Button fSelectAll;
private Button fDeselectAll;
private IWorkingSet[] fResult;
private List fAddedWorkingSets;
private List fRemovedWorkingSets;
private Map fEditedWorkingSets;
private List fRemovedMRUWorkingSets;
private int nextButtonId = IDialogConstants.CLIENT_ID + 1;
public WorkingSetConfigurationDialog(Shell parentShell,
IWorkingSet[] allWorkingSets, IWorkingSet[] activeWorkingSets) {
super(parentShell);
setTitle(WorkingSetMessages.WorkingSetConfigurationDialog_title);
setMessage(WorkingSetMessages.WorkingSetConfigurationDialog_message);
fAllWorkingSets = new ArrayList(allWorkingSets.length);
fActiveWorkingSets = Arrays.asList(activeWorkingSets);
Filter filter = new Filter();
for (int i = 0; i < allWorkingSets.length; i++) {
if (filter.select(null, null, allWorkingSets[i]))
fAllWorkingSets.add(allWorkingSets[i]);
}
setShellStyle(getShellStyle() | SWT.RESIZE);
}
/**
* Returns the selected working sets
*
* @return the selected working sets
*/
public IWorkingSet[] getSelection() {
return fResult;
}
/**
* Sets the initial selection
*
* @param workingSets
* the initial selection
*/
public void setSelection(IWorkingSet[] workingSets) {
fResult = workingSets;
setInitialSelections(workingSets);
}
/**
* {@inheritDoc}
*/
@Override
protected Control createContents(Composite parent) {
Control control = super.createContents(parent);
setInitialSelection();
updateButtonAvailability();
return control;
}
/**
* {@inheritDoc}
*/
@Override
protected Control createDialogArea(Composite parent) {
Composite composite = (Composite) super.createDialogArea(parent);
composite.setFont(parent.getFont());
createMessageArea(composite);
Composite inner = new Composite(composite, SWT.NONE);
inner.setFont(composite.getFont());
inner.setLayoutData(new GridData(GridData.FILL_BOTH));
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.marginHeight = 0;
layout.marginWidth = 0;
inner.setLayout(layout);
createTableViewer(inner);
createOrderButtons(inner);
createModifyButtons(composite);
fTableViewer.setInput(fAllWorkingSets);
return composite;
}
private void createTableViewer(Composite parent) {
fTableViewer = CheckboxTableViewer.newCheckList(parent,
SWT.BORDER | SWT.MULTI);
fTableViewer.addCheckStateListener(event -> updateButtonAvailability());
GridData data = new GridData(GridData.FILL_BOTH);
data.heightHint = convertHeightInCharsToPixels(20);
data.widthHint = convertWidthInCharsToPixels(50);
fTableViewer.getTable().setLayoutData(data);
fTableViewer.getTable().setFont(parent.getFont());
fTableViewer.addFilter(new Filter());
fTableViewer.setLabelProvider(new WorkingSetLabelProvider());
fTableViewer.setContentProvider(new IStructuredContentProvider() {
@Override
public Object[] getElements(Object element) {
return ((List) element).toArray();
}
@Override
public void dispose() {
}
@Override
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
}
});
fTableViewer
.addSelectionChangedListener(event -> handleSelectionChanged());
}
private void createModifyButtons(Composite composite) {
Composite buttonComposite = new Composite(composite, SWT.RIGHT);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
buttonComposite.setLayout(layout);
GridData data = new GridData(
GridData.HORIZONTAL_ALIGN_END | GridData.GRAB_HORIZONTAL);
data.grabExcessHorizontalSpace = true;
composite.setData(data);
fNewButton = createButton(buttonComposite, nextButtonId++,
WorkingSetMessages.WorkingSetConfigurationDialog_new_label,
false);
fNewButton.setFont(composite.getFont());
fNewButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
createWorkingSet();
}
});
fEditButton = createButton(buttonComposite, nextButtonId++,
WorkingSetMessages.WorkingSetConfigurationDialog_edit_label,
false);
fEditButton.setFont(composite.getFont());
fEditButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
editSelectedWorkingSet();
}
});
fRemoveButton = createButton(buttonComposite, nextButtonId++,
WorkingSetMessages.WorkingSetConfigurationDialog_remove_label,
false);
fRemoveButton.setFont(composite.getFont());
fRemoveButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
removeSelectedWorkingSets();
}
});
}
private void createOrderButtons(Composite parent) {
Composite buttons = new Composite(parent, SWT.NONE);
buttons.setFont(parent.getFont());
buttons.setLayoutData(new GridData(GridData.FILL_VERTICAL));
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
buttons.setLayout(layout);
fUpButton = new Button(buttons, SWT.PUSH);
fUpButton.setText(
WorkingSetMessages.WorkingSetConfigurationDialog_up_label);
fUpButton.setFont(parent.getFont());
setButtonLayoutData(fUpButton);
fUpButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
moveUp(fTableViewer.getStructuredSelection().toList());
}
});
fDownButton = new Button(buttons, SWT.PUSH);
fDownButton.setText(
WorkingSetMessages.WorkingSetConfigurationDialog_down_label);
fDownButton.setFont(parent.getFont());
setButtonLayoutData(fDownButton);
fDownButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
moveDown(fTableViewer.getStructuredSelection().toList());
}
});
fSelectAll = new Button(buttons, SWT.PUSH);
fSelectAll.setText(
WorkingSetMessages.WorkingSetConfigurationDialog_selectAll_label);
fSelectAll.setFont(parent.getFont());
setButtonLayoutData(fSelectAll);
fSelectAll.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
selectAll();
}
});
fDeselectAll = new Button(buttons, SWT.PUSH);
fDeselectAll.setText(
WorkingSetMessages.WorkingSetConfigurationDialog_deselectAll_label);
fDeselectAll.setFont(parent.getFont());
setButtonLayoutData(fDeselectAll);
fDeselectAll.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
deselectAll();
}
});
}
/**
* {@inheritDoc}
*/
@Override
protected void okPressed() {
List newResult = getResultWorkingSets();
fResult = (IWorkingSet[]) newResult
.toArray(new IWorkingSet[newResult.size()]);
setResult(newResult);
super.okPressed();
}
private List getResultWorkingSets() {
Object[] checked = fTableViewer.getCheckedElements();
return new ArrayList(Arrays.asList(checked));
}
/**
* {@inheritDoc}
*/
@Override
protected void cancelPressed() {
restoreAddedWorkingSets();
restoreChangedWorkingSets();
restoreRemovedWorkingSets();
super.cancelPressed();
}
private void setInitialSelection() {
List selections = getInitialElementSelections();
if (!selections.isEmpty()) {
fTableViewer.setCheckedElements(selections.toArray());
}
}
private void createWorkingSet() {
IWorkingSetManager manager = PlatformUI.getWorkbench()
.getWorkingSetManager();
IWorkingSetNewWizard wizard = manager.createWorkingSetNewWizard(
new String[] { WorkingSetIDs.SCRIPT });
// the wizard can't be null since we have at least the Script working
// set.
WizardDialog dialog = new WizardDialog(getShell(), wizard);
dialog.create();
if (dialog.open() == Window.OK) {
IWorkingSet workingSet = wizard.getSelection();
Filter filter = new Filter();
if (filter.select(null, null, workingSet)) {
fAllWorkingSets.add(workingSet);
fTableViewer.add(workingSet);
fTableViewer.setSelection(new StructuredSelection(workingSet),
true);
fTableViewer.setChecked(workingSet, true);
manager.addWorkingSet(workingSet);
fAddedWorkingSets.add(workingSet);
}
}
}
private void editSelectedWorkingSet() {
IWorkingSetManager manager = PlatformUI.getWorkbench()
.getWorkingSetManager();
IWorkingSet editWorkingSet = (IWorkingSet) ((IStructuredSelection) fTableViewer
.getSelection()).getFirstElement();
IWorkingSetEditWizard wizard = manager
.createWorkingSetEditWizard(editWorkingSet);
WizardDialog dialog = new WizardDialog(getShell(), wizard);
IWorkingSet originalWorkingSet = (IWorkingSet) fEditedWorkingSets
.get(editWorkingSet);
boolean firstEdit = originalWorkingSet == null;
// save the original working set values for restoration when selection
// dialog is cancelled.
if (firstEdit) {
originalWorkingSet = PlatformUI.getWorkbench()
.getWorkingSetManager()
.createWorkingSet(editWorkingSet.getName(),
editWorkingSet.getElements());
} else {
fEditedWorkingSets.remove(editWorkingSet);
}
dialog.create();
if (dialog.open() == Window.OK) {
editWorkingSet = wizard.getSelection();
fTableViewer.update(editWorkingSet, null);
// make sure ok button is enabled when the selected working set
// is edited. Fixes bug 33386.
updateButtonAvailability();
}
fEditedWorkingSets.put(editWorkingSet, originalWorkingSet);
}
/**
* Called when the selection has changed.
*/
void handleSelectionChanged() {
updateButtonAvailability();
}
/**
* Overrides method in Dialog
*
* @see org.eclipse.jface.dialogs.Dialog#open()
*/
@Override
public int open() {
fAddedWorkingSets = new ArrayList();
fRemovedWorkingSets = new ArrayList();
fEditedWorkingSets = new HashMap();
fRemovedMRUWorkingSets = new ArrayList();
return super.open();
}
/**
* Removes the selected working sets from the workbench.
*/
private void removeSelectedWorkingSets() {
ISelection selection = fTableViewer.getSelection();
if (selection instanceof IStructuredSelection) {
IWorkingSetManager manager = PlatformUI.getWorkbench()
.getWorkingSetManager();
Iterator iter = ((IStructuredSelection) selection).iterator();
while (iter.hasNext()) {
IWorkingSet workingSet = (IWorkingSet) iter.next();
if (fAddedWorkingSets.contains(workingSet)) {
fAddedWorkingSets.remove(workingSet);
} else {
IWorkingSet[] recentWorkingSets = manager
.getRecentWorkingSets();
for (int i = 0; i < recentWorkingSets.length; i++) {
if (workingSet.equals(recentWorkingSets[i])) {
fRemovedMRUWorkingSets.add(workingSet);
break;
}
}
fRemovedWorkingSets.add(workingSet);
}
fAllWorkingSets.remove(workingSet);
manager.removeWorkingSet(workingSet);
}
fTableViewer.remove(((IStructuredSelection) selection).toArray());
}
}
/**
* Removes newly created working sets from the working set manager.
*/
private void restoreAddedWorkingSets() {
IWorkingSetManager manager = PlatformUI.getWorkbench()
.getWorkingSetManager();
Iterator iterator = fAddedWorkingSets.iterator();
while (iterator.hasNext()) {
manager.removeWorkingSet(((IWorkingSet) iterator.next()));
}
}
/**
* Rolls back changes to working sets.
*/
private void restoreChangedWorkingSets() {
Iterator iterator = fEditedWorkingSets.keySet().iterator();
while (iterator.hasNext()) {
IWorkingSet editedWorkingSet = (IWorkingSet) iterator.next();
IWorkingSet originalWorkingSet = (IWorkingSet) fEditedWorkingSets
.get(editedWorkingSet);
if (editedWorkingSet.getName()
.equals(originalWorkingSet.getName()) == false) {
editedWorkingSet.setName(originalWorkingSet.getName());
}
if (editedWorkingSet.getElements()
.equals(originalWorkingSet.getElements()) == false) {
editedWorkingSet.setElements(originalWorkingSet.getElements());
}
}
}
/**
* Adds back removed working sets to the working set manager.
*/
private void restoreRemovedWorkingSets() {
IWorkingSetManager manager = PlatformUI.getWorkbench()
.getWorkingSetManager();
Iterator iterator = fRemovedWorkingSets.iterator();
while (iterator.hasNext()) {
manager.addWorkingSet(((IWorkingSet) iterator.next()));
}
iterator = fRemovedMRUWorkingSets.iterator();
while (iterator.hasNext()) {
manager.addRecentWorkingSet(((IWorkingSet) iterator.next()));
}
}
/**
* Updates the modify buttons' enabled state based on the current seleciton.
*/
private void updateButtonAvailability() {
IStructuredSelection selection = fTableViewer.getStructuredSelection();
boolean hasSelection = !selection.isEmpty();
boolean hasSingleSelection = selection.size() == 1;
fRemoveButton
.setEnabled(hasSelection && areAllGlobalWorkingSets(selection));
fEditButton.setEnabled(hasSingleSelection
&& ((IWorkingSet) selection.getFirstElement()).isEditable());
if (fUpButton != null) {
fUpButton.setEnabled(canMoveUp());
}
if (fDownButton != null) {
fDownButton.setEnabled(canMoveDown());
}
}
private boolean areAllGlobalWorkingSets(IStructuredSelection selection) {
Set globals = new HashSet(Arrays.asList(PlatformUI.getWorkbench()
.getWorkingSetManager().getWorkingSets()));
for (Iterator iter = selection.iterator(); iter.hasNext();) {
if (!globals.contains(iter.next()))
return false;
}
return true;
}
private void moveUp(List toMoveUp) {
if (toMoveUp.size() > 0) {
setElements(moveUp(fAllWorkingSets, toMoveUp));
fTableViewer.reveal(toMoveUp.get(0));
}
}
private void moveDown(List toMoveDown) {
if (toMoveDown.size() > 0) {
setElements(reverse(moveUp(reverse(fAllWorkingSets), toMoveDown)));
fTableViewer.reveal(toMoveDown.get(toMoveDown.size() - 1));
}
}
private void setElements(List elements) {
fAllWorkingSets = elements;
fTableViewer.setInput(fAllWorkingSets);
updateButtonAvailability();
}
private List moveUp(List elements, List move) {
int nElements = elements.size();
List res = new ArrayList(nElements);
Object floating = null;
for (int i = 0; i < nElements; i++) {
Object curr = elements.get(i);
if (move.contains(curr)) {
res.add(curr);
} else {
if (floating != null) {
res.add(floating);
}
floating = curr;
}
}
if (floating != null) {
res.add(floating);
}
return res;
}
private List reverse(List p) {
List reverse = new ArrayList(p.size());
for (int i = p.size() - 1; i >= 0; i--) {
reverse.add(p.get(i));
}
return reverse;
}
private boolean canMoveUp() {
int[] indc = fTableViewer.getTable().getSelectionIndices();
for (int i = 0; i < indc.length; i++) {
if (indc[i] != i) {
return true;
}
}
return false;
}
private boolean canMoveDown() {
int[] indc = fTableViewer.getTable().getSelectionIndices();
int k = fAllWorkingSets.size() - 1;
for (int i = indc.length - 1; i >= 0; i--, k--) {
if (indc[i] != k) {
return true;
}
}
return false;
}
// ---- select / deselect --------------------------------------------------
private void selectAll() {
fTableViewer.setAllChecked(true);
}
private void deselectAll() {
fTableViewer.setAllChecked(false);
}
}