| /******************************************************************************* |
| * Copyright (c) 2000, 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 |
| *******************************************************************************/ |
| 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; |
| } |
| } |