blob: 516cc3ccb9a04859252978780e258b6d8f3dfe58 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 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
*******************************************************************************/
package org.eclipse.ant.internal.ui.preferences;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.ant.core.Property;
import org.eclipse.ant.internal.core.IAntCoreConstants;
import org.eclipse.ant.internal.ui.AntUIPlugin;
import org.eclipse.ant.internal.ui.AntUtil;
import org.eclipse.ant.internal.ui.ColumnSorter;
import org.eclipse.ant.internal.ui.IAntUIConstants;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ColumnLayoutData;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
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.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.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import com.ibm.icu.text.MessageFormat;
public class AntPropertiesBlock {
/**
* Constant representing the id of the settings for the property table column widths
*
* @since 3.5
*/
private static final String PROPERTY_COLUMN_WIDTH = "ant.properties.block.property.columnWidth"; //$NON-NLS-1$
/**
* Constant representing the id of the settings for the property table sort column
*
* @since 3.5
*/
private static final String PROPERTY_SORT_COLUMN = "ant.properties.block.property.sortColumn"; //$NON-NLS-1$
/**
* Constant representing the id of the settings for the property table sort direction
*
* @since 3.5
*/
private static final String PROPERTY_SORT_DIRECTION = "ant.properties.block.property.sortDirection"; //$NON-NLS-1$
private IAntBlockContainer container;
private Button editButton;
private Button removeButton;
private Button addButton;
private Button addFileButton;
private Button addExternalFileButton;
private Button removeFileButton;
private TableViewer propertyTableViewer;
private TableViewer fileTableViewer;
private final AntObjectLabelProvider labelProvider = new AntObjectLabelProvider();
private IDialogSettings dialogSettings;
private boolean tablesEnabled = true;
private final String[] fTableColumnHeaders = { AntPreferencesMessages.AntPropertiesBlock_0, AntPreferencesMessages.AntPropertiesBlock_5,
AntPreferencesMessages.AntPropertiesBlock_6 };
private final ColumnLayoutData[] fTableColumnLayouts = { new ColumnWeightData(30), // , 190, true),
new ColumnWeightData(40), // , 190, true),
new ColumnWeightData(30) // , 190, true)
};
/**
* Button listener that delegates for widget selection events.
*/
private SelectionAdapter buttonListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
if (event.widget == addButton) {
addProperty();
} else if (event.widget == editButton) {
edit();
} else if (event.widget == removeButton) {
remove(propertyTableViewer);
} else if (event.widget == addFileButton) {
addPropertyFile();
} else if (event.widget == addExternalFileButton) {
addExternalPropertyFile();
} else if (event.widget == removeFileButton) {
remove(fileTableViewer);
}
}
};
/**
* Key listener that delegates for key pressed events.
*/
private KeyAdapter keyListener = new KeyAdapter() {
@Override
public void keyPressed(KeyEvent event) {
if (event.getSource() == propertyTableViewer) {
if (removeButton.isEnabled() && event.character == SWT.DEL && event.stateMask == 0) {
remove(propertyTableViewer);
}
} else if (event.getSource() == fileTableViewer) {
if (removeFileButton.isEnabled() && event.character == SWT.DEL && event.stateMask == 0) {
remove(fileTableViewer);
}
}
}
};
/**
* Selection changed listener that delegates selection events.
*/
private ISelectionChangedListener tableListener = new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
if (tablesEnabled) {
if (event.getSource() == propertyTableViewer) {
propertyTableSelectionChanged((IStructuredSelection) event.getSelection());
} else if (event.getSource() == fileTableViewer) {
fileTableSelectionChanged((IStructuredSelection) event.getSelection());
}
}
}
};
public AntPropertiesBlock(IAntBlockContainer container) {
this.container = container;
}
private void addPropertyFile() {
String title = AntPreferencesMessages.AntPropertiesFileSelectionDialog_12;
String message = AntPreferencesMessages.AntPropertiesFileSelectionDialog_13;
String filterExtension = "properties"; //$NON-NLS-1$
String filterMessage = AntPreferencesMessages.AntPropertiesFileSelectionDialog_14;
Object[] existingFiles = getPropertyFiles();
List<IFile> propFiles = new ArrayList<>(existingFiles.length);
for (int j = 0; j < existingFiles.length; j++) {
String file = (String) existingFiles[j];
try {
propFiles.add(AntUtil.getFileForLocation(VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(file), null));
}
catch (CoreException e) {
AntUIPlugin.log(e.getStatus());
}
}
FileSelectionDialog dialog = new FileSelectionDialog(propertyTableViewer.getControl().getShell(), propFiles, title, message, filterExtension, filterMessage);
if (dialog.open() == Window.OK) {
Object[] elements = dialog.getResult();
for (int i = 0; i < elements.length; i++) {
IFile file = (IFile) elements[i];
String varExpression = VariablesPlugin.getDefault().getStringVariableManager().generateVariableExpression("workspace_loc", file.getFullPath().toString()); //$NON-NLS-1$
((AntContentProvider) fileTableViewer.getContentProvider()).add(varExpression);
}
container.update();
}
}
public void createControl(Composite top, String propertyLabel, String propertyFileLabel) {
Font font = top.getFont();
dialogSettings = AntUIPlugin.getDefault().getDialogSettings();
Label label = new Label(top, SWT.NONE);
GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalSpan = 2;
label.setLayoutData(gd);
label.setFont(font);
label.setText(propertyLabel);
int idx = 0;
int direction = SWT.DOWN;
try {
idx = dialogSettings.getInt(PROPERTY_SORT_COLUMN);
direction = dialogSettings.getInt(PROPERTY_SORT_DIRECTION);
}
catch (NumberFormatException e) {
// do nothing
}
propertyTableViewer = createTableViewer(top, true, false, idx, direction);
propertyTableViewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
if (!event.getSelection().isEmpty() && editButton.isEnabled()) {
edit();
}
}
});
propertyTableViewer.getTable().addKeyListener(keyListener);
createButtonGroup(top);
label = new Label(top, SWT.NONE);
gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.horizontalSpan = 2;
label.setLayoutData(gd);
label.setFont(font);
label.setText(propertyFileLabel);
fileTableViewer = createTableViewer(top, false, true, 0, SWT.DOWN);
fileTableViewer.getTable().addKeyListener(keyListener);
createButtonGroup(top);
}
/**
* Creates the group which will contain the buttons.
*/
private void createButtonGroup(Composite top) {
Composite buttonGroup = new Composite(top, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
buttonGroup.setLayout(layout);
buttonGroup.setLayoutData(new GridData(GridData.FILL_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL));
buttonGroup.setFont(top.getFont());
addButtonsToButtonGroup(buttonGroup);
}
/**
* Creates and returns a configured table viewer in the given parent
*/
private TableViewer createTableViewer(Composite parent, boolean setColumns, boolean defaultsorting, int sortcolumnidx, int sortdirection) {
Table table = new Table(parent, SWT.MULTI | SWT.FULL_SELECTION | SWT.BORDER);
GridData data = new GridData(GridData.FILL_BOTH);
int availableRows = availableRows(parent);
if (setColumns) {
data.heightHint = table.getItemHeight() * (availableRows / 10);
}
data.widthHint = 425;
table.setLayoutData(data);
table.setFont(parent.getFont());
TableViewer tableViewer = new TableViewer(table);
tableViewer.setContentProvider(new AntContentProvider(defaultsorting));
tableViewer.setLabelProvider(labelProvider);
tableViewer.addSelectionChangedListener(tableListener);
if (setColumns) {
TableLayout tableLayout = new TableLayout();
table.setLayout(tableLayout);
table.setHeaderVisible(true);
table.setLinesVisible(true);
ColumnSorter sorter = null;
for (int i = 0; i < fTableColumnHeaders.length; i++) {
tableLayout.addColumnData(fTableColumnLayouts[i]);
TableColumn column = new TableColumn(table, SWT.NONE, i);
column.setResizable(fTableColumnLayouts[i].resizable);
column.setText(fTableColumnHeaders[i]);
sorter = new ColumnSorter(tableViewer, column) {
@Override
public String getCompareText(Object obj, int columnindex) {
return AntPropertiesBlock.this.labelProvider.getColumnText(obj, columnindex);
}
};
if (i == sortcolumnidx) {
sorter.setDirection(sortdirection);
}
}
}
return tableViewer;
}
/**
* Used to persist any settings for the block that the user has set
*
* @since 3.5
*/
public void saveSettings() {
if (propertyTableViewer != null) {
saveColumnSettings();
}
}
/**
* Persist table settings into the give dialog store.
*
* @since 3.5
*/
private void saveColumnSettings() {
Table table = this.propertyTableViewer.getTable();
int columnCount = table.getColumnCount();
for (int i = 0; i < columnCount; i++) {
dialogSettings.put(PROPERTY_COLUMN_WIDTH + i, table.getColumn(i).getWidth());
}
TableColumn column = table.getSortColumn();
if (column != null) {
dialogSettings.put(PROPERTY_SORT_COLUMN, table.indexOf(column));
dialogSettings.put(PROPERTY_SORT_DIRECTION, table.getSortDirection());
}
}
/**
* Restore table settings from the given dialog store.
*
* @since 3.5
*/
private void restoreColumnSettings() {
if (this.propertyTableViewer == null) {
return;
}
restoreColumnWidths();
}
/**
* Restores the column widths from dialog settings
*
* @since 3.5
*/
private void restoreColumnWidths() {
Table table = this.propertyTableViewer.getTable();
int columnCount = table.getColumnCount();
for (int i = 0; i < columnCount; i++) {
int width = -1;
try {
width = dialogSettings.getInt(PROPERTY_COLUMN_WIDTH + i);
}
catch (NumberFormatException e) {
// do nothing
}
if ((width <= 0) || (i == table.getColumnCount() - 1)) {
table.getColumn(i).pack();
} else {
table.getColumn(i).setWidth(width);
}
}
}
/**
* Return the number of rows available in the current display using the current font.
*
* @param parent
* The Composite whose Font will be queried.
* @return The result of the display size divided by the font size.
*/
private int availableRows(Composite parent) {
int fontHeight = (parent.getFont().getFontData())[0].getHeight();
int displayHeight = parent.getDisplay().getClientArea().height;
return displayHeight / fontHeight;
}
/*
* (non-Javadoc) Method declared on AntPage.
*/
protected void addButtonsToButtonGroup(Composite parent) {
if (editButton == null) {
addButton = createPushButton(parent, AntPreferencesMessages.AntPropertiesBlock_1);
editButton = createPushButton(parent, AntPreferencesMessages.AntPropertiesBlock_2);
removeButton = createPushButton(parent, AntPreferencesMessages.AntPropertiesBlock_3);
} else {
addFileButton = createPushButton(parent, AntPreferencesMessages.AntPropertiesBlock_4);
addExternalFileButton = createPushButton(parent, AntPreferencesMessages.AntPropertiesBlock_14);
removeFileButton = createPushButton(parent, AntPreferencesMessages.AntPropertiesBlock_removeFileButton);
}
}
/**
* Creates and returns a configured button in the given composite with the given label. Widget selection call-backs for the returned button will
* be processed by the <code>buttonListener</code>
*/
private Button createPushButton(Composite parent, String label) {
Button button = container.createPushButton(parent, label);
button.addSelectionListener(buttonListener);
GridData gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL);
button.setLayoutData(gridData);
return button;
}
/**
* Allows the user to enter external property files
*/
private void addExternalPropertyFile() {
String lastUsedPath;
lastUsedPath = dialogSettings.get(IAntUIConstants.DIALOGSTORE_LASTEXTFILE);
if (lastUsedPath == null) {
lastUsedPath = IAntCoreConstants.EMPTY_STRING;
}
FileDialog dialog = new FileDialog(fileTableViewer.getControl().getShell(), SWT.MULTI | SWT.SHEET);
dialog.setFilterExtensions(new String[] { "*.properties", "*.*" }); //$NON-NLS-1$ //$NON-NLS-2$ ;
dialog.setFilterPath(lastUsedPath);
String result = dialog.open();
if (result == null) {
return;
}
IPath filterPath = new Path(dialog.getFilterPath());
String[] results = dialog.getFileNames();
for (int i = 0; i < results.length; i++) {
String fileName = results[i];
IPath path = filterPath.append(fileName).makeAbsolute();
((AntContentProvider) fileTableViewer.getContentProvider()).add(path.toOSString());
}
dialogSettings.put(IAntUIConstants.DIALOGSTORE_LASTEXTFILE, filterPath.toOSString());
container.update();
}
private void remove(TableViewer viewer) {
AntContentProvider antContentProvider = (AntContentProvider) viewer.getContentProvider();
IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
antContentProvider.remove(sel);
container.update();
}
/**
* Allows the user to enter a user property
*/
private void addProperty() {
String title = AntPreferencesMessages.AntPropertiesBlock_Add_Property_2;
AddPropertyDialog dialog = new AddPropertyDialog(propertyTableViewer.getControl().getShell(), title, new String[] {
IAntCoreConstants.EMPTY_STRING, IAntCoreConstants.EMPTY_STRING });
if (dialog.open() == Window.CANCEL) {
return;
}
String[] pair = dialog.getNameValuePair();
String name = pair[0];
if (!overwrite(name)) {
return;
}
Property prop = new Property();
prop.setName(name);
prop.setValue(pair[1]);
((AntContentProvider) propertyTableViewer.getContentProvider()).add(prop);
container.update();
}
private void edit() {
IStructuredSelection selection = (IStructuredSelection) propertyTableViewer.getSelection();
Property prop = (Property) selection.getFirstElement();
String originalName = prop.getName();
String title = AntPreferencesMessages.AntPropertiesBlock_Edit_User_Property_5;
AddPropertyDialog dialog = new AddPropertyDialog(propertyTableViewer.getControl().getShell(), title, new String[] { prop.getName(),
prop.getValue(false) });
if (dialog.open() == Window.CANCEL) {
return;
}
String[] pair = dialog.getNameValuePair();
String name = pair[0];
if (!name.equals(originalName)) {
if (!overwrite(name)) {
return;
}
}
prop.setName(name);
prop.setValue(pair[1]);
// trigger a resort
propertyTableViewer.refresh();
container.update();
}
private boolean overwrite(String name) {
Object[] properties = getProperties();
for (int i = 0; i < properties.length; i++) {
Property property = (Property) properties[i];
String propertyName = property.getName();
if (propertyName.equals(name)) {
if (property.isDefault()) {
MessageDialog.openError(propertyTableViewer.getControl().getShell(), AntPreferencesMessages.AntPropertiesBlock_17, MessageFormat.format(AntPreferencesMessages.AntPropertiesBlock_18, new Object[] {
propertyName, property.getPluginLabel() }));
return false;
}
boolean overWrite = MessageDialog.openQuestion(propertyTableViewer.getControl().getShell(), AntPreferencesMessages.AntPropertiesBlock_15, MessageFormat.format(AntPreferencesMessages.AntPropertiesBlock_16, new Object[] { name }));
if (!overWrite) {
return false;
}
((AntContentProvider) propertyTableViewer.getContentProvider()).remove(property);
break;
}
}
return true;
}
/**
* Handles selection changes in the Property file table viewer.
*/
private void fileTableSelectionChanged(IStructuredSelection newSelection) {
removeFileButton.setEnabled(newSelection.size() > 0);
}
/**
* Handles selection changes in the Property table viewer.
*/
private void propertyTableSelectionChanged(IStructuredSelection newSelection) {
int size = newSelection.size();
boolean enabled = true;
Iterator<Object> itr = newSelection.iterator();
while (itr.hasNext()) {
Object element = itr.next();
if (element instanceof Property) {
Property property = (Property) element;
if (property.isDefault()) {
enabled = false;
break;
}
}
}
editButton.setEnabled(enabled && size == 1);
removeButton.setEnabled(enabled && size > 0);
}
public void populatePropertyViewer(Map<String, String> properties) {
if (properties == null) {
propertyTableViewer.setInput(new Property[0]);
return;
}
Property[] result = new Property[properties.size()];
Iterator<Map.Entry<String, String>> entries = properties.entrySet().iterator();
int i = 0;
while (entries.hasNext()) {
Entry<String, String> element = entries.next();
Property property = new Property();
property.setName(element.getKey());
property.setValue(element.getValue());
result[i] = property;
i++;
}
propertyTableViewer.setInput(result);
restoreColumnSettings();
}
public void setPropertiesInput(Property[] properties) {
propertyTableViewer.setInput(properties);
}
public void setPropertyFilesInput(String[] files) {
fileTableViewer.setInput(files);
}
public void update() {
propertyTableSelectionChanged((IStructuredSelection) propertyTableViewer.getSelection());
fileTableSelectionChanged((IStructuredSelection) fileTableViewer.getSelection());
}
public Object[] getProperties() {
return ((AntContentProvider) propertyTableViewer.getContentProvider()).getElements(null);
}
public Object[] getPropertyFiles() {
return ((AntContentProvider) fileTableViewer.getContentProvider()).getElements(null);
}
public void setEnabled(boolean enable) {
setTablesEnabled(enable);
addButton.setEnabled(enable);
addExternalFileButton.setEnabled(enable);
addFileButton.setEnabled(enable);
editButton.setEnabled(enable);
removeButton.setEnabled(enable);
removeFileButton.setEnabled(enable);
if (enable) {
propertyTableViewer.setSelection(propertyTableViewer.getSelection());
fileTableViewer.setSelection(fileTableViewer.getSelection());
}
}
public void setTablesEnabled(boolean tablesEnabled) {
this.tablesEnabled = tablesEnabled;
}
}