package com.sysdeo.eclipse.tomcat.editors; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.ArrayList; import java.util.StringTokenizer; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.preference.ListEditor; import org.eclipse.jface.util.Assert; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; 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.List; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Widget; import com.sysdeo.eclipse.tomcat.TomcatPluginResources; public class ListFieldEditor extends ListEditor implements TomcatPluginResources { /** * The list widget; <code>null</code> if none (before creation or after * disposal). */ protected List list; /** * The button box containing the Add, Remove, Up, and Down buttons; * <code>null</code> if none (before creation or after disposal). */ protected Composite buttonBox; protected Button addButton; protected Button removeButton; protected Button updateButton; protected Button upButton; protected Button downButton; /** * The selection listener. */ protected SelectionListener selectionListener; /** * Creates a new list field editor */ public ListFieldEditor() { } /** * Creates a list field editor. * * @param name * the name of the preference this field editor works on * @param labelText * the label text of the field editor * @param parent * the parent of the field editor's control */ public ListFieldEditor(String name, String labelText, Composite parent) { init(name, labelText); createControl(parent); } /** * Notifies that the Add button has been pressed. */ protected void addPressed() { setPresentsDefaultValue(false); String input = getNewInputObject(); if (input != null) { int index = list.getSelectionIndex(); if (index >= 0) list.add(input, index + 1); else list.add(input, 0); selectionChanged(); } } /** * Notifies that the Add button has been pressed. */ protected void updatePressed() { String input = getNewInputObject(); if (input != null) { int index = list.getSelectionIndex(); if (index >= 0) list.setItem(index, input); selectionChanged(); } } /* * (non-Javadoc) Method declared on FieldEditor. */ protected void adjustForNumColumns(int numColumns) { Control control = getLabelControl(); ((GridData) control.getLayoutData()).horizontalSpan = numColumns; ((GridData) list.getLayoutData()).horizontalSpan = numColumns - 1; } /** * Creates the Add, Remove, Up, and Down button in the given button box. * * @param buttonBox * the box for the buttons */ protected void createButtons(Composite buttonBox) { addButton = createPushButton(buttonBox, PREF_PAGE_ADDBUTTON_LABEL); //$NON-NLS-1$ removeButton = createPushButton(buttonBox, PREF_PAGE_REMOVEBUTTON_LABEL); //$NON-NLS-1$ updateButton = createPushButton(buttonBox, PREF_PAGE_UPDATEBUTTON_LABEL); //$NON-NLS-1$ upButton = createPushButton(buttonBox, PREF_PAGE_UPBUTTON_LABEL); //$NON-NLS-1$ downButton = createPushButton(buttonBox, PREF_PAGE_DOWNBUTTON_LABEL); //$NON-NLS-1$ } /** * Helper method to create a push button. * * @param parent * the parent control * @param key * the resource name used to supply the button's label text */ protected Button createPushButton(Composite parent, String label) { Button button = new Button(parent, SWT.PUSH); button.setText(label); GridData data = new GridData(GridData.FILL_HORIZONTAL); data.heightHint = convertVerticalDLUsToPixels(button, IDialogConstants.BUTTON_HEIGHT); int widthHint = convertHorizontalDLUsToPixels(button, IDialogConstants.BUTTON_WIDTH); data.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x); // data.horizontalSpan = hs; use to have multiple buttons on the same // row button.setLayoutData(data); button.addSelectionListener(getSelectionListener()); return button; } /** * Creates a selection listener. */ public void createSelectionListener() { selectionListener = new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { Widget widget = event.widget; if (widget == addButton) { addPressed(); } else if (widget == removeButton) { removePressed(); } else if (widget == updateButton) { updatePressed(); } else if (widget == upButton) { upPressed(); } else if (widget == downButton) { downPressed(); } else if (widget == list) { selectionChanged(); } } }; } /* * (non-Javadoc) Method declared on FieldEditor. */ protected void doFillIntoGrid(Composite parent, int numColumns) { Control control = getLabelControl(parent); GridData gd = new GridData(); gd.horizontalSpan = numColumns; control.setLayoutData(gd); list = getListControl(parent); gd = new GridData(GridData.FILL_HORIZONTAL); gd.heightHint = 80; gd.widthHint = 300; gd.verticalAlignment = GridData.FILL; gd.horizontalSpan = numColumns - 1; gd.horizontalAlignment = GridData.FILL; gd.grabExcessHorizontalSpace = true; list.setLayoutData(gd); buttonBox = getButtonBoxControl(parent); gd = new GridData(); gd.verticalAlignment = GridData.BEGINNING; buttonBox.setLayoutData(gd); } /* * (non-Javadoc) Method declared on FieldEditor. */ protected void doLoad() { if (list != null) { String s = getPreferenceStore().getString(getPreferenceName()); String[] array = parseString(s); for (int i = 0; i < array.length; i++) { list.add(array[i]); } } } /* * (non-Javadoc) Method declared on FieldEditor. */ protected void doLoadDefault() { if (list != null) { list.removeAll(); String s = getPreferenceStore().getDefaultString(getPreferenceName()); String[] array = parseString(s); for (int i = 0; i < array.length; i++) { list.add(array[i]); } } } /* * (non-Javadoc) Method declared on FieldEditor. */ protected void doStore() { String s = createList(list.getItems()); if (s != null) getPreferenceStore().setValue(getPreferenceName(), s); } /** * Notifies that the Down button has been pressed. */ protected void downPressed() { swap(false); } /** * Returns this field editor's button box containing the Add, Remove, Up, * and Down button. * * @param parent * the parent control * @return the button box */ public Composite getButtonBoxControl(Composite parent) { if (buttonBox == null) { buttonBox = new Composite(parent, SWT.NULL); GridLayout layout = new GridLayout(); layout.numColumns = 1; // change value to have multiple buttons on // the same row layout.marginWidth = 0; layout.marginHeight = 0; layout.verticalSpacing = 0; buttonBox.setLayout(layout); createButtons(buttonBox); buttonBox.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent event) { addButton = null; removeButton = null; upButton = null; downButton = null; buttonBox = null; } }); } else { checkParent(buttonBox, parent); } selectionChanged(); return buttonBox; } /** * Returns this field editor's list control. * * @param parent * the parent control * @return the list control */ public List getListControl(Composite parent) { if (list == null) { list = new List(parent, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL); list.addSelectionListener(getSelectionListener()); list.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent event) { list = null; } }); } else { checkParent(list, parent); } return list; } /* * (non-Javadoc) Method declared on FieldEditor. */ public int getNumberOfControls() { return 2; } /** * Returns this field editor's selection listener. The listener is created * if nessessary. * * @return the selection listener */ protected SelectionListener getSelectionListener() { if (selectionListener == null) createSelectionListener(); return selectionListener; } /** * Returns this field editor's shell. * <p> * This method is internal to the framework; subclassers should not call * this method. * </p> * * @return the shell */ protected Shell getShell() { if (addButton == null) return null; return addButton.getShell(); } /** * Notifies that the Remove button has been pressed. */ protected void removePressed() { setPresentsDefaultValue(false); int[] indices = list.getSelectionIndices(); if (indices.length > 0) { list.remove(indices); selectionChanged(); } } /** * Notifies that the list selection has changed. */ protected void selectionChanged() { int index = list.getSelectionIndex(); int size = list.getItemCount(); removeButton.setEnabled(index >= 0); upButton.setEnabled(size > 1 && index > 0); downButton.setEnabled(size > 1 && index >= 0 && index < size - 1); } /* * (non-Javadoc) Method declared on FieldEditor. */ public void setFocus() { if (list != null) { list.setFocus(); } } /** * Moves the currently selected item up or down. * * @param up * <code>true</code> if the item should move up, and * <code>false</code> if it should move down */ protected void swap(boolean up) { setPresentsDefaultValue(false); int index = list.getSelectionIndex(); int target = up ? index - 1 : index + 1; if (index >= 0) { String[] selection = list.getSelection(); if (selection.length == 1) { list.remove(index); list.add(selection[0], target); list.setSelection(target); } } selectionChanged(); } /** * Notifies that the Up button has been pressed. */ protected void upPressed() { swap(true); } /** * Combines the given list of items into a single string. This method is the * converse of <code>parseString</code>. * <p> * Subclasses must implement this method. * </p> * * @param items * the list of items * @return the combined string * @see #parseString */ protected String createList(String[] items) { StringBuffer path = new StringBuffer(""); for (int i = 0; i < items.length; i++) { path.append(URLEncoder.encode(items[i])); path.append(TomcatPluginResources.PREF_PAGE_LIST_SEPARATOR); } return path.toString(); } /** * Creates and returns a new item for the list. * <p> * Subclasses must implement this method. * </p> * * @return a new item */ protected String getNewInputObject() { String defaultValue = ""; if (list.getSelection().length != 0) { defaultValue = list.getSelection()[0]; } InputDialog dialog = new InputDialog(getShell(), "New Tomcat JVM paramater", "Enter a JVM parameter", defaultValue, null); String param = null; int dialogCode = dialog.open(); if (dialogCode == InputDialog.OK) { param = dialog.getValue(); if (param != null) { param = param.trim(); if (param.length() == 0) return null; } } return param; } /** * Splits the given string into a list of strings. This method is the * converse of <code>createList</code>. * <p> * Subclasses must implement this method. * </p> * * @param stringList * the string * @return an array of <code>String</code> * @see #createList */ protected String[] parseString(String stringList) { StringTokenizer st = new StringTokenizer(stringList, TomcatPluginResources.PREF_PAGE_LIST_SEPARATOR); //$NON-NLS-1$ ArrayList v = new ArrayList(); while (st.hasMoreTokens()) { v.add(URLDecoder.decode(st.nextToken())); } return (String[]) v.toArray(new String[v.size()]); } }