/******************************************************************************* * Copyright (c) 2000, 2013 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.debug.internal.ui.preferences; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.variables.IStringVariableManager; import org.eclipse.core.variables.IValueVariable; import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.debug.internal.core.IInternalDebugCoreConstants; import org.eclipse.debug.internal.ui.DebugUIPlugin; import org.eclipse.debug.internal.ui.IDebugHelpContextIds; import org.eclipse.debug.internal.ui.MultipleInputDialog; import org.eclipse.debug.internal.ui.SWTFactory; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.jface.viewers.ColumnLayoutData; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IColorProvider; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; 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.SelectionChangedEvent; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.viewers.ViewerFilter; 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.Color; 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.Display; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import org.eclipse.ui.PlatformUI; import com.ibm.icu.text.MessageFormat; /** * Preference page for creating and configuring simple * launch variables. * * @see org.eclipse.debug.core.variables.IValueVariable * @see org.eclipse.debug.core.variables.ISimpleVariableRegistry */ public class StringVariablePreferencePage extends PreferencePage implements IWorkbenchPreferencePage { private TableViewer variableTable; protected Button envAddButton; protected Button envEditButton; protected Button envRemoveButton; protected SimpleVariableContentProvider variableContentProvider= new SimpleVariableContentProvider(); protected static final String NAME_LABEL= DebugPreferencesMessages.SimpleVariablePreferencePage_10; protected static final String VALUE_LABEL = DebugPreferencesMessages.SimpleVariablePreferencePage_11; protected static final String DESCRIPTION_LABEL = DebugPreferencesMessages.SimpleVariablePreferencePage_12; protected static final String STRING_VARIABLE_PREFERENCE_KEY = "StringVariablePreferencePage"; //$NON-NLS-1$ protected static String[] variableTableColumnProperties= { "variable", //$NON-NLS-1$ "value", //$NON-NLS-1$ "description" //$NON-NLS-1$ }; protected String[] variableTableColumnHeaders= { DebugPreferencesMessages.SimpleVariablePreferencePage_3, DebugPreferencesMessages.SimpleVariablePreferencePage_4, DebugPreferencesMessages.SimpleVariablePreferencePage_5, DebugPreferencesMessages.StringVariablePreferencePage_27 }; protected ColumnLayoutData[] variableTableColumnLayouts= { new ColumnWeightData(30), new ColumnWeightData(25), new ColumnWeightData(25), new ColumnWeightData(20) }; public StringVariablePreferencePage() { setDescription(DebugPreferencesMessages.SimpleVariablePreferencePage_6); } /** * @see PreferencePage#createControl(Composite) */ @Override public void createControl(Composite parent) { super.createControl(parent); PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IDebugHelpContextIds.SIMPLE_VARIABLE_PREFERENCE_PAGE); } @Override protected Control createContents(Composite parent) { noDefaultAndApplyButton(); Font font= parent.getFont(); //The main composite Composite composite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginHeight=0; layout.marginWidth=0; layout.numColumns= 2; composite.setLayout(layout); composite.setFont(font); createTable(composite); createButtons(composite); return composite; } /** * Creates and configures the table containing launch configuration variables * and their associated value. */ private void createTable(Composite parent) { Font font= parent.getFont(); // Create table composite Composite tableComposite = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginHeight = 0; layout.marginWidth = 0; layout.numColumns = 1; GridData gridData = new GridData(GridData.FILL_BOTH); gridData.heightHint = 150; gridData.widthHint = 400; tableComposite.setLayout(layout); tableComposite.setLayoutData(gridData); tableComposite.setFont(font); // Create table variableTable = new TableViewer(tableComposite, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION); Table table = variableTable.getTable(); table.setHeaderVisible(true); table.setLinesVisible(true); table.setFont(font); gridData = new GridData(GridData.FILL_BOTH); variableTable.getControl().setLayoutData(gridData); variableTable.setContentProvider(variableContentProvider); variableTable.setColumnProperties(variableTableColumnProperties); variableTable.addFilter(new VariableFilter()); variableTable.setComparator(new ViewerComparator() { @Override public int compare(Viewer iViewer, Object e1, Object e2) { if (e1 == null) { return -1; } else if (e2 == null) { return 1; } else { return ((VariableWrapper)e1).getName().compareToIgnoreCase(((VariableWrapper)e2).getName()); } } }); variableTable.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { handleTableSelectionChanged(event); } }); variableTable.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(DoubleClickEvent event) { if (!variableTable.getSelection().isEmpty()) { handleEditButtonPressed(); } } }); variableTable.getTable().addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent event) { if (event.character == SWT.DEL && event.stateMask == 0) { handleRemoveButtonPressed(); } } }); for (int i = 0; i < variableTableColumnHeaders.length; i++) { TableColumn tc = new TableColumn(table, SWT.NONE, i); tc.setResizable(variableTableColumnLayouts[i].resizable); tc.setText(variableTableColumnHeaders[i]); } // Try restoring column widths from preferences, if widths aren't stored, init columns to default if (!restoreColumnWidths()){ restoreDefaultColumnWidths(); } variableTable.setInput(getVariableManager()); variableTable.setLabelProvider(new SimpleVariableLabelProvider()); } /** * Creates the new/edit/remove buttons for the variable table * @param parent the composite in which the buttons should be created */ private void createButtons(Composite parent) { // Create button composite Composite buttonComposite = new Composite(parent, SWT.NONE); GridLayout glayout = new GridLayout(); glayout.marginHeight = 0; glayout.marginWidth = 0; glayout.numColumns = 1; GridData gdata = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); buttonComposite.setLayout(glayout); buttonComposite.setLayoutData(gdata); buttonComposite.setFont(parent.getFont()); // Create buttons envAddButton = SWTFactory.createPushButton(buttonComposite, DebugPreferencesMessages.SimpleVariablePreferencePage_7, null); envAddButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { handleAddButtonPressed(); } }); envEditButton = SWTFactory.createPushButton(buttonComposite, DebugPreferencesMessages.SimpleVariablePreferencePage_8, null); envEditButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { handleEditButtonPressed(); } }); envEditButton.setEnabled(false); envRemoveButton = SWTFactory.createPushButton(buttonComposite, DebugPreferencesMessages.SimpleVariablePreferencePage_9, null); envRemoveButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { handleRemoveButtonPressed(); } }); envRemoveButton.setEnabled(false); } private void handleAddButtonPressed() { boolean done = false; String name = null; String description = null; String value = null; while (!done){ MultipleInputDialog dialog= new MultipleInputDialog(getShell(), DebugPreferencesMessages.SimpleVariablePreferencePage_13); dialog.addTextField(NAME_LABEL, name, false); dialog.addBrowseField(VALUE_LABEL, value, true); dialog.addTextField(DESCRIPTION_LABEL, description, true); if (dialog.open() != Window.OK) { done = true; } else { name= dialog.getStringValue(NAME_LABEL).trim(); value = dialog.getStringValue(VALUE_LABEL); description= dialog.getStringValue(DESCRIPTION_LABEL); done = addVariable(name, description, value); } } } /** * Attempts to create and add a new variable with the given properties. Returns * whether the operation completed successfully (either the variable was added * successfully, or the user cancelled the operation). Returns false if the name * is null or the user chooses not to overwrite an existing variable. * * @param name name of the variable, cannot be null or empty. * @param description description of the variable or null * @param value value of the variable or null * @return whether the operation completed successfully */ private boolean addVariable(String name, String description, String value) { if (name == null || name.length() == 0){ MessageDialog.openError(getShell(),DebugPreferencesMessages.StringVariablePreferencePage_21, DebugPreferencesMessages.StringVariablePreferencePage_20); return false; } List editedVariables = variableContentProvider.getWorkingSetVariables(); Iterator iter = editedVariables.iterator(); while (iter.hasNext()) { VariableWrapper currentVariable = iter.next(); if (!currentVariable.isRemoved()) { String currentName = currentVariable.getName(); if (currentName.equals(name)) { if (currentVariable.isReadOnly()){ MessageDialog.openError(getShell(), DebugPreferencesMessages.StringVariablePreferencePage_23, MessageFormat.format(DebugPreferencesMessages.StringVariablePreferencePage_22, new Object[] { name })); return false; } else { MessageDialog dialog = new MessageDialog(getShell(), DebugPreferencesMessages.SimpleVariablePreferencePage_15, null, MessageFormat.format(DebugPreferencesMessages.SimpleVariablePreferencePage_16, new Object[] { name }), MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }, 0); int overWrite= dialog.open(); if (overWrite == 0) { currentVariable.setValue(value); currentVariable.setDescription(description); variableTable.update(currentVariable, null); return true; } else if(overWrite == 1){ return false; } else { return true; // Cancel was pressed, return true so operation is ended } } } } } VariableWrapper newVariable = new VariableWrapper(name, description, value); variableContentProvider.addVariable(newVariable); variableTable.refresh(); return true; } private void handleEditButtonPressed() { IStructuredSelection selection= (IStructuredSelection) variableTable.getSelection(); VariableWrapper variable= (VariableWrapper) selection.getFirstElement(); if (variable == null || variable.isReadOnly()) { return; } String value= variable.getValue(); String description= variable.getDescription(); String name= variable.getName(); MultipleInputDialog dialog = new MultipleInputDialog(getShell(), MessageFormat.format(DebugPreferencesMessages.SimpleVariablePreferencePage_14, new Object[] { name })); dialog.addBrowseField(VALUE_LABEL, value, true); dialog.addTextField(DESCRIPTION_LABEL, description, true); if (dialog.open() == Window.OK) { value= dialog.getStringValue(VALUE_LABEL); description= dialog.getStringValue(DESCRIPTION_LABEL); if (value != null) { variable.setValue(value); } if (description != null) { variable.setDescription(description); } variableTable.update(variable, null); } } /** * Remove the selection variables. */ private void handleRemoveButtonPressed() { IStructuredSelection selection= (IStructuredSelection) variableTable.getSelection(); List variablesToRemove = selection.toList(); StringBuffer contributedVariablesToRemove= new StringBuffer(); Iterator iter = variablesToRemove.iterator(); while (iter.hasNext()) { VariableWrapper variable = iter.next(); if (variable.isContributed()) { contributedVariablesToRemove.append('\t').append(variable.getName()).append('\n'); } } if (contributedVariablesToRemove.length() > 0) { boolean remove = MessageDialog.openQuestion(getShell(), DebugPreferencesMessages.SimpleLaunchVariablePreferencePage_21, MessageFormat.format(DebugPreferencesMessages.SimpleLaunchVariablePreferencePage_22, new Object[] { contributedVariablesToRemove.toString() })); // if (!remove) { return; } } VariableWrapper[] variables= variablesToRemove.toArray(new VariableWrapper[0]); for (int i = 0; i < variables.length; i++) { variables[i].setRemoved(true); } variableTable.refresh(); } /** * Responds to a selection changed event in the variable table * @param event the selection change event */ protected void handleTableSelectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = ((IStructuredSelection)event.getSelection()); VariableWrapper variable= (VariableWrapper) selection.getFirstElement(); if (variable == null || variable.isReadOnly()) { envEditButton.setEnabled(false); envRemoveButton.setEnabled(false); } else { envEditButton.setEnabled(selection.size() == 1); envRemoveButton.setEnabled(selection.size() > 0); } } @Override public void init(IWorkbench workbench) { } /** * Clear the variables. */ @Override protected void performDefaults() { variableContentProvider.init(); variableTable.refresh(); super.performDefaults(); } /** * Sets the saved state for reversion. */ @Override public boolean performOk() { variableContentProvider.saveChanges(); saveColumnWidths(); return super.performOk(); } /** * Returns the DebugPlugin's singleton instance of the * launch variable manager * @return the singleton instance of the simple variable registry. */ private IStringVariableManager getVariableManager() { return VariablesPlugin.getDefault().getStringVariableManager(); } public void saveColumnWidths() { StringBuffer widthPreference = new StringBuffer(); for (int i = 0; i < variableTable.getTable().getColumnCount(); i++) { widthPreference.append(variableTable.getTable().getColumn(i).getWidth()); widthPreference.append(','); } if (widthPreference.length() > 0){ DebugUIPlugin.getDefault().getPreferenceStore().setValue(STRING_VARIABLE_PREFERENCE_KEY, widthPreference.toString()); } } private boolean restoreColumnWidths() { String[] columnWidthStrings = DebugUIPlugin.getDefault().getPreferenceStore().getString(STRING_VARIABLE_PREFERENCE_KEY).split(","); //$NON-NLS-1$ int columnCount = variableTable.getTable().getColumnCount(); if (columnWidthStrings.length != columnCount){ return false; // Preferred column sizes not stored correctly. } for (int i = 0; i < columnCount; i++) { try{ int columnWidth = Integer.parseInt(columnWidthStrings[i]); variableTable.getTable().getColumn(i).setWidth(columnWidth); } catch (NumberFormatException e){ DebugUIPlugin.log(new Throwable("Problem loading persisted column sizes for StringVariablePreferencesPage",e)); //$NON-NLS-1$ } } return true; } private void restoreDefaultColumnWidths(){ TableLayout layout = new TableLayout(); for (int i = 0; i < variableTableColumnLayouts.length; i++) { layout.addColumnData(variableTableColumnLayouts[i]); } variableTable.getTable().setLayout(layout); } private class SimpleVariableContentProvider implements IStructuredContentProvider { /** * The content provider stores variable wrappers for use during editing. */ private List fWorkingSet = new ArrayList(); @Override public Object[] getElements(Object inputElement) { return fWorkingSet.toArray(); } /** * Adds the given variable to the 'wrappers' * * @param variable variable to add */ public void addVariable(VariableWrapper variable) { fWorkingSet.add(variable); } @Override public void dispose() { } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { if (newInput == null || !(newInput instanceof IStringVariableManager)){ return; } init(); } /** * Saves the edited variable state to the variable manager. */ public void saveChanges() { IStringVariableManager manager = getVariableManager(); Iterator iterator = fWorkingSet.iterator(); List remove = new ArrayList(); List add = new ArrayList(); while (iterator.hasNext()) { VariableWrapper variable = iterator.next(); if (!variable.isReadOnly()) { IValueVariable underlyingVariable = variable.getUnderlyingVariable(); if (variable.isRemoved()) { if (underlyingVariable != null) { // if added and removed there is no underlying variable remove.add(underlyingVariable); } } else if (variable.isAdded()) { IValueVariable vv = manager.newValueVariable(variable.getName(), variable.getDescription()); vv.setValue(variable.getValue()); add.add(vv); } else if (variable.isChanged()) { underlyingVariable.setValue(variable.getValue()); underlyingVariable.setDescription(variable.getDescription()); } } } // remove if (!remove.isEmpty()) { manager.removeVariables(remove.toArray(new IValueVariable[remove.size()])); } // add if (!add.isEmpty()) { try { manager.addVariables(add.toArray(new IValueVariable[add.size()])); } catch (CoreException e) { DebugUIPlugin.errorDialog(getShell(), DebugPreferencesMessages.StringVariablePreferencePage_24, DebugPreferencesMessages.StringVariablePreferencePage_25, e.getStatus()); // } } } /** * Re-initializes to the variables currently stored in the manager. */ public void init() { fWorkingSet.clear(); IStringVariableManager manager = getVariableManager(); IValueVariable[] variables = manager.getValueVariables(); for (int i = 0; i < variables.length; i++) { fWorkingSet.add(new VariableWrapper(variables[i])); } } /** * Returns the 'working set' of variables * * @return the working set of variables (not yet saved) */ public List getWorkingSetVariables() { return fWorkingSet; } } class VariableWrapper { protected IValueVariable fVariable; protected String fNewName = null; protected String fNewDesc = null; protected String fNewValue = null; boolean fRemoved = false; boolean fAdded = false; public VariableWrapper(IValueVariable variable) { fVariable = variable; } public VariableWrapper(String name, String desc, String value) { fNewName = name; fNewDesc = desc; fNewValue = value; fAdded = true; } public boolean isAdded() { return fAdded; } public String getName() { if (fNewName == null) { return fVariable.getName(); } return fNewName; } public void setName(String name) { fNewName = name; } public String getDescription() { if (fNewDesc == null) { return fVariable.getDescription(); } return fNewDesc; } public String getValue() { if (fNewValue == null) { return fVariable.getValue(); } return fNewValue; } public void setValue(String value) { fNewValue = value; } public void setDescription(String desc) { fNewDesc = desc; } public boolean isChanged() { return !fAdded && !fRemoved && (fNewValue != null || fNewDesc != null); } public boolean isReadOnly() { if (fVariable == null) { return false; } return fVariable.isReadOnly(); } public boolean isContributed() { if (fVariable == null) { return false; } return fVariable.isContributed(); } public IValueVariable getUnderlyingVariable() { return fVariable; } public boolean isRemoved() { return fRemoved; } public void setRemoved(boolean removed) { fRemoved = removed; } } private class SimpleVariableLabelProvider extends LabelProvider implements ITableLabelProvider, IColorProvider { @Override public Image getColumnImage(Object element, int columnIndex) { return null; } @Override public String getColumnText(Object element, int columnIndex) { if (element instanceof VariableWrapper) { VariableWrapper variable= (VariableWrapper) element; switch (columnIndex) { case 0 : StringBuffer name = new StringBuffer(); name.append(variable.getName()); if (variable.isReadOnly()){ name.append(DebugPreferencesMessages.StringVariablePreferencePage_26); } return name.toString(); case 1: String value= variable.getValue(); if (value == null) { value= IInternalDebugCoreConstants.EMPTY_STRING; } return value; case 2: String description= variable.getDescription(); if (description == null) { description= IInternalDebugCoreConstants.EMPTY_STRING; } return description; case 3: String contribution = IInternalDebugCoreConstants.EMPTY_STRING; if (variable.isContributed()) { String pluginId = getVariableManager().getContributingPluginId(variable.getUnderlyingVariable()); if (pluginId != null) { contribution = pluginId; } else { contribution = DebugPreferencesMessages.SimpleLaunchVariablePreferencePage_23; } } return contribution; default: break; } } return null; } @Override public Color getForeground(Object element) { if (element instanceof VariableWrapper) { if (((VariableWrapper) element).isReadOnly()) { Display display= Display.getCurrent(); return display.getSystemColor(SWT.COLOR_INFO_FOREGROUND); } } return null; } @Override public Color getBackground(Object element) { if (element instanceof VariableWrapper) { if (((VariableWrapper) element).isReadOnly()) { Display display= Display.getCurrent(); return display.getSystemColor(SWT.COLOR_INFO_BACKGROUND); } } return null; } } class VariableFilter extends ViewerFilter { /* (non-Javadoc) * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) */ @Override public boolean select(Viewer viewer, Object parentElement, Object element) { return !((VariableWrapper)element).isRemoved(); } } }