blob: b1f4ef8ce548106e92f6cf2c38ca6fb38b7cc74c [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
*
* Contributors:
* xored software, Inc. - initial API and Implementation
*******************************************************************************/
package org.eclipse.dltk.validators.internal.ui;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.internal.ui.util.SWTUtil;
import org.eclipse.dltk.internal.ui.util.TableLayoutComposite;
import org.eclipse.dltk.ui.util.PixelConverter;
import org.eclipse.dltk.validators.core.IValidator;
import org.eclipse.dltk.validators.core.IValidatorType;
import org.eclipse.dltk.validators.core.ValidatorRuntime;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
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.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
/**
* A composite that displays installed InterpreterEnvironment's in a table.
* InterpreterEnvironments can be added, removed, edited, and searched for.
* <p>
* This block implements ISelectionProvider - it sends selection change events
* when the checked InterpreterEnvironment in the table changes, or when the
* "use default" button check state changes.
* </p>
*/
public class ValidatorBlock implements IAddValidatorDialogRequestor {
/**
* This block's control
*/
private Composite fControl;
/**
* Validators being displayed
*/
protected List<IValidator> fValidators = new ArrayList<>();
/**
* The main list control
*/
protected CheckboxTableViewer fValidatorList;
// Action buttons
private Button fAddButton;
private Button fRemoveButton;
private Button fEditButton;
private Button fCopyButton;
// index of column used for sorting
private int fSortColumn = 0;
private Table fTable;
/**
* Content provider to show a list of InterpreterEnvironments
*/
private static class ValidatorContentProvider
implements IStructuredContentProvider {
@Override
public Object[] getElements(Object input) {
return ((List) input).toArray();
}
@Override
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
}
@Override
public void dispose() {
}
}
/**
* Label provider for installed InterpreterEnvironments table.
*/
private static class ValidatorLabelProvider extends LabelProvider
implements ITableLabelProvider {
/**
* @see ITableLabelProvider#getColumnText(Object, int)
*/
@Override
public String getColumnText(Object element, int columnIndex) {
if (element instanceof IValidator) {
IValidator validator = (IValidator) element;
switch (columnIndex) {
case 0:
return validator.getName();
case 1:
return validator.getValidatorType().getName();
case 2:
String nature = validator.getValidatorType().getNature();
if (ValidatorRuntime.ANY_NATURE.equals(nature)) {
return ValidatorMessages.ValidatorBlock_all;
}
IDLTKLanguageToolkit languageToolkit = DLTKLanguageManager
.getLanguageToolkit(nature);
if (languageToolkit != null) {
return languageToolkit.getLanguageName();
}
return ValidatorMessages.ValidatorBlock_unknown;
}
}
return element.toString();
}
/**
* @see ITableLabelProvider#getColumnImage(Object, int)
*/
@Override
public Image getColumnImage(Object element, int columnIndex) {
if (columnIndex == 0) {
// TODO: insert validator logo here
}
return null;
}
}
/**
* Creates this block's control in the given control.
*
* @param ancestor
* containing control
* @param useManageButton
* whether to present a single 'manage...' button
* to the user that opens the installed
* InterpreterEnvironments pref page for
* InterpreterEnvironment management, or to
* provide 'add, remove, edit, and search'
* buttons.
*/
public void createControl(Composite ancestor) {
Composite parent = new Composite(ancestor, SWT.NULL);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
layout.marginHeight = 0;
layout.marginWidth = 0;
Font font = ancestor.getFont();
parent.setFont(font);
parent.setLayout(layout);
fControl = parent;
GridData data;
Label tableLabel = new Label(parent, SWT.NONE);
tableLabel.setText(ValidatorMessages.InstalledValidatorBlock_15);
data = new GridData();
data.horizontalSpan = 2;
tableLabel.setLayoutData(data);
tableLabel.setFont(font);
PixelConverter conv = new PixelConverter(parent);
data = new GridData(GridData.FILL_BOTH);
data.widthHint = conv.convertWidthInCharsToPixels(50);
TableLayoutComposite tblComposite = new TableLayoutComposite(parent,
SWT.NONE);
tblComposite.setLayoutData(data);
fTable = new Table(tblComposite,
SWT.CHECK | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);
data = new GridData(GridData.FILL_BOTH);
data.widthHint = 450;
fTable.setLayoutData(data);
fTable.setFont(font);
fTable.setHeaderVisible(true);
fTable.setLinesVisible(true);
TableColumn column1 = new TableColumn(fTable, SWT.NULL);
column1.setText(ValidatorMessages.InstalledValidatorBlock_0);
column1.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
sortByName();
}
});
TableColumn column2 = new TableColumn(fTable, SWT.NULL);
column2.setText(ValidatorMessages.InstalledValidatorBlock_2);
column2.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
sortByType();
}
});
TableColumn column3 = new TableColumn(fTable, SWT.NULL);
column3.setText(ValidatorMessages.InstalledValidatorBlock_1);
// column3.addSelectionListener(new SelectionAdapter() {
// public void widgetSelected(SelectionEvent e) {
// sortByLocation();
// }
// });
fValidatorList = new CheckboxTableViewer(fTable);
fValidatorList.setLabelProvider(new ValidatorLabelProvider());
fValidatorList.setContentProvider(new ValidatorContentProvider());
fValidatorList.addCheckStateListener(event -> {
IValidator validator = (IValidator) event.getElement();
validator.setAutomatic(event.getChecked());
});
// by default, sort by name
sortByName();
fValidatorList.addSelectionChangedListener(evt -> enableButtons());
fValidatorList.addDoubleClickListener(e -> {
if (!fValidatorList.getSelection().isEmpty()) {
editValidator();
}
});
fTable.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent event) {
if (event.character == SWT.DEL && event.stateMask == 0) {
if (fRemoveButton.getEnabled())
removeValidator();
}
}
});
Composite buttons = new Composite(parent, SWT.NULL);
buttons.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
buttons.setLayout(layout);
buttons.setFont(font);
fAddButton = createPushButton(buttons,
ValidatorMessages.InstalledValidatorBlock_3);
fAddButton.addListener(SWT.Selection, evt -> addValidator());
fEditButton = createPushButton(buttons,
ValidatorMessages.InstalledValidatorBlock_4);
fEditButton.addListener(SWT.Selection, evt -> editValidator());
fCopyButton = createPushButton(buttons,
ValidatorMessages.InstalledValidatorBlock_16);
fCopyButton.addListener(SWT.Selection, evt -> copyValidator());
fRemoveButton = createPushButton(buttons,
ValidatorMessages.InstalledValidatorBlock_5);
fRemoveButton.addListener(SWT.Selection, evt -> removeValidator());
// copied from ListDialogField.CreateSeparator()
Label separator = new Label(buttons, SWT.NONE);
separator.setVisible(false);
GridData gd = new GridData();
gd.horizontalAlignment = GridData.FILL;
gd.verticalAlignment = GridData.BEGINNING;
gd.heightHint = 4;
separator.setLayoutData(gd);
fillWithWorkspaceValidators();
enableButtons();
}
/**
* Sorts by Interpreter type, and name within type.
*/
private void sortByType() {
fValidatorList.setComparator(new ViewerComparator() {
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
if ((e1 instanceof IValidator) && (e2 instanceof IValidator)) {
IValidator left = (IValidator) e1;
IValidator right = (IValidator) e2;
String leftType = left.getValidatorType().getName();
String rightType = right.getValidatorType().getName();
int res = leftType.compareToIgnoreCase(rightType);
if (res != 0) {
return res;
}
return left.getName().compareToIgnoreCase(right.getName());
}
return super.compare(viewer, e1, e2);
}
@Override
public boolean isSorterProperty(Object element, String property) {
return true;
}
});
fSortColumn = 3;
}
/**
* Sorts by Interpreter name.
*/
private void sortByName() {
fValidatorList.setComparator(new ViewerComparator() {
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
if ((e1 instanceof IValidator) && (e2 instanceof IValidator)) {
IValidator left = (IValidator) e1;
IValidator right = (IValidator) e2;
String name = left.getName();
if (name == null) {
return 0;
}
return name.compareToIgnoreCase(right.getName());
}
return super.compare(viewer, e1, e2);
}
@Override
public boolean isSorterProperty(Object element, String property) {
return true;
}
});
fSortColumn = 1;
}
private void enableButtons() {
IStructuredSelection selection = fValidatorList
.getStructuredSelection();
int selectionCount = selection.size();
boolean addEnabled = ValidatorRuntime
.getPossibleValidatorTypes().length > 0;
boolean editEnabled = selectionCount == 1;
boolean removeEnabled = true;
boolean copyEnabled = false && selectionCount > 0;// not implemented
if (selectionCount > 0) {
Iterator<?> iterator = selection.iterator();
while (iterator.hasNext()) {
IValidator install = (IValidator) iterator.next();
if (isContributed(install)) {
removeEnabled = false;
copyEnabled = false;
}
}
} else {
removeEnabled = false;
}
fAddButton.setEnabled(addEnabled);
fEditButton.setEnabled(editEnabled);
fRemoveButton.setEnabled(removeEnabled);
fCopyButton.setEnabled(copyEnabled);
}
protected Button createPushButton(Composite parent, String label) {
return SWTUtil.createPushButton(parent, label, null);
}
private boolean isContributed(IValidator install) {
return install.getValidatorType().isBuiltin();
}
/**
* Returns this block's control
*
* @return control
*/
public Control getControl() {
return fControl;
}
/**
* Sets the InterpreterEnvironments to be displayed in this block
*
* @param validators
* InterpreterEnvironments to be displayed
*/
protected void setValidators(IValidator[] validators) {
fValidators.clear();
List<IValidator> automatic = new ArrayList<>();
for (int i = 0; i < validators.length; i++) {
if (validators[i].isAutomatic()) {
automatic.add(validators[i]);
}
fValidators.add(validators[i]);
}
fValidatorList.setInput(fValidators);
fValidatorList.setCheckedElements(automatic.toArray());
fValidatorList.refresh();
}
/**
* Returns the InterpreterEnvironments currently being displayed in this
* block
*
* @return InterpreterEnvironments currently being displayed in this block
*/
public IValidator[] getValidators() {
return fValidators.toArray(new IValidator[fValidators.size()]);
}
/**
* @see IAddValidatorDialogRequestor#isDuplicateName(String)
*/
@Override
public boolean isDuplicateName(String name) {
for (int i = 0; i < fValidators.size(); i++) {
IValidator validator = fValidators.get(i);
String validatorName = validator.getName();
if (validatorName == null) {
return true;
}
if (validatorName.equals(name)) {
return true;
}
}
return false;
}
private void removeValidator() {
IStructuredSelection selection = fValidatorList
.getStructuredSelection();
IValidator[] validators = new IValidator[selection.size()];
int i = 0;
for (Iterator<?> iter = selection.iterator(); iter.hasNext();) {
validators[i++] = (IValidator) iter.next();
}
removeValidators(validators);
}
/**
* Removes the given {@link IValidator}s from the table.
*
* @param validators
*/
public void removeValidators(IValidator[] validators) {
for (int i = 0; i < validators.length; i++) {
fValidators.remove(validators[i]);
}
fValidatorList.refresh();
}
protected Shell getShell() {
return getControl().getShell();
}
/**
* Persist table settings into the give dialog store, prefixed with the
* given key.
*
* @param settings
* dialog store
* @param qualifier
* key qualifier
*/
public void saveColumnSettings(IDialogSettings settings, String qualifier) {
int columnCount = fTable.getColumnCount();
for (int i = 0; i < columnCount; i++) {
settings.put(qualifier + ".columnWidth" + i, //$NON-NLS-1$
fTable.getColumn(i).getWidth());
}
settings.put(qualifier + ".sortColumn", fSortColumn); //$NON-NLS-1$
}
/**
* Restore table settings from the given dialog store using the given key.
*
* @param settings
* dialog settings store
* @param qualifier
* key to restore settings from
*/
public void restoreColumnSettings(IDialogSettings settings,
String qualifier) {
fValidatorList.getTable().layout(true);
restoreColumnWidths(settings, qualifier);
try {
fSortColumn = settings.getInt(qualifier + ".sortColumn"); //$NON-NLS-1$
} catch (NumberFormatException e) {
fSortColumn = 1;
}
switch (fSortColumn) {
case 1:
sortByName();
break;
case 2:
// sortByLocation();
break;
case 3:
sortByType();
break;
}
}
private void restoreColumnWidths(IDialogSettings settings,
String qualifier) {
int columnCount = fTable.getColumnCount();
for (int i = 0; i < columnCount; i++) {
int width = -1;
try {
width = settings.getInt(qualifier + ".columnWidth" + i); //$NON-NLS-1$
} catch (NumberFormatException e) {
}
if (width <= 0) {
fTable.getColumn(i).pack();
} else {
fTable.getColumn(i).setWidth(width);
}
}
}
/**
* Populates the InterpreterEnvironment table with existing
* InterpreterEnvironments defined in the workspace.
*/
protected void fillWithWorkspaceValidators() {
List<IValidator> all = new ArrayList<>();
IValidatorType[] types = ValidatorRuntime.getValidatorTypes();
for (int i = 0; i < types.length; i++) {
final IValidatorType type = types[i];
if (type.isBuiltin() && !type.isConfigurable())
continue;
IValidator[] validators = type.getValidators();
if (validators != null) {
for (int j = 0; j < validators.length; j++) {
all.add(validators[j].getWorkingCopy());
}
}
}
setValidators(all.toArray(new IValidator[all.size()]));
}
@Override
public void validatorAdded(IValidator validator) {
fValidators.add(validator);
fValidatorList.add(validator);
fValidatorList.setChecked(validator, validator.isAutomatic());
fValidatorList.setSelection(new StructuredSelection(validator));
}
// Make sure that Validatortandin ids are unique if multiple calls to
// System.currentTimeMillis()
// happen very quickly
private static String fgLastUsedID;
/**
* Find a unique Interpreter id. Check existing 'real' Validator, as well as
* the last id used for a Validatortandin.
*/
protected String createUniqueId(IValidatorType InterpreterType) {
String id = null;
do {
id = String.valueOf(System.currentTimeMillis());
} while (InterpreterType.findValidator(id) != null
|| id.equals(fgLastUsedID));
fgLastUsedID = id;
return id;
}
/**
* Compares the given name against current names and adds the appropriate
* numerical suffix to ensure that it is unique.
*
* @param name
* the name with which to ensure uniqueness
* @return the unique version of the given name
*
*/
protected String generateName(String name) {
if (!isDuplicateName(name)) {
return name;
}
if (name.matches(".*\\(\\d*\\)")) { //$NON-NLS-1$
int start = name.lastIndexOf('(');
int end = name.lastIndexOf(')');
String stringInt = name.substring(start + 1, end);
int numericValue = Integer.parseInt(stringInt);
String newName = name.substring(0, start + 1) + (numericValue + 1)
+ ")"; //$NON-NLS-1$
return generateName(newName);
} else {
return generateName(name + " (1)"); //$NON-NLS-1$
}
}
protected void copyValidator() {
// IStructuredSelection selection = (IStructuredSelection)
// fValidatorList.getSelection();
// Iterator it = selection.iterator();
//
// ArrayList newEntries = new ArrayList();
// while (it.hasNext()) {
// IValidator selectedInterpreter = (IValidator) it.next();
//
// // duplicate & add Interpreter
// IValidator standin = new IValidator(selectedInterpreter,
// createUniqueId(selectedInterpreter.getValidatorType()));
// standin.setName(generateName(selectedInterpreter.getName()));
// // AddDLTKInterpreterDialog dialog =
// createInterpreterDialog(standin);
// dialog.setTitle(ValidatorMessages.InstalledValidatorBlock_18);
// if (dialog.open() != Window.OK) {
// return;
// }
// newEntries.add(standin);
// fValidator.add(standin);
// }
// fValidatorList.refresh();
// fValidatorList.setSelection(new
// StructuredSelection(newEntries.toArray()));
}
/**
* Bring up a dialog that lets the user create a new Interpreter definition.
*/
protected void addValidator() {
AddValidatorDialog dialog = new AddValidatorDialog(this, getShell(),
ValidatorRuntime.getPossibleValidatorTypes(), null);
dialog.setTitle(ValidatorMessages.InstalledValidatorBlock_7);
if (dialog.open() != Window.OK) {
dialog.removeValidators(true);
return;
} else {
dialog.removeValidators(false);
}
fValidatorList.refresh();
}
protected void editValidator() {
IStructuredSelection selection = fValidatorList
.getStructuredSelection();
IValidator validator = (IValidator) selection.getFirstElement();
if (validator == null) {
return;
}
AddValidatorDialog dialog = new AddValidatorDialog(this, getShell(),
ValidatorRuntime.getValidatorTypes(), validator);
dialog.setTitle(ValidatorMessages.InstalledValidatorBlock_8);
if (dialog.open() != Window.OK) {
return;
}
fValidatorList.refresh(validator);
}
}