Community
Participate
Working Groups
Certainly, it's not a big deal, but, org.eclipse.jface.preference.ListEditor ought to allow multiple selection as an option.
Here's some code that I modified to allow it in a configurable way...there's probably more error checking that needs to be done: class MultiSelectListEditor extends FieldEditor { /** style settings to allow add button */ public static int ALLOW_ADD = 1 >> 0; /** style settings to allow remove button */ public static int ALLOW_REMOVE = 1 << 1; /** style settings to allow up button */ public static int ALLOW_UP = 1 << 2; /** style settings to allow down button */ public static int ALLOW_DOWN = 1 << 3; /** style settings to allow all buttons */ public static int ALLOW_ALL = ALLOW_ADD | ALLOW_REMOVE | ALLOW_UP | ALLOW_DOWN; /** Controls which buttons are displayed */ private int allowButtons = ALLOW_ALL; /** Controls whether the list allows multiple items to be selected */ private boolean multipleSelections; /** * The list widget; <code>null</code> if none * (before creation or after disposal). */ private List list; /** * The button box containing the Add, Remove, Up, and Down buttons; * <code>null</code> if none (before creation or after disposal). */ private Composite buttonBox; /** * The Add button. */ private Button addButton; /** * The Remove button. */ private Button removeButton; /** * The Up button. */ private Button upButton; /** * The Down button. */ private Button downButton; /** * The selection listener. */ private SelectionListener selectionListener; /** * Creates a new list field editor */ protected MultiSelectListEditor() { } /** * 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 * @param buttons controls which buttons are visible. To show all, * use 0 or ALLOW_ALL. * @param mutltiSelect controls whether the list allows mutliple * selections */ protected MultiSelectListEditor(String name, String labelText, Composite parent, int buttons, boolean multiSelect) { allowButtons = buttons; multipleSelections = multiSelect; init(name, labelText); createControl(parent); } /** * Create a list field editor with mutliple selection allowed and add, remove, up, down buttons * * @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 */ protected MultiSelectListEditor(String name, String labelText, Composite parent) { this(name, labelText, parent, ALLOW_ALL, true); } /** * Notifies that the Add button has been pressed. */ private 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(); } } /* (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 box the box for the buttons */ private void createButtons(Composite box) { if ((allowButtons&ALLOW_ADD)==ALLOW_ADD) addButton = createPushButton(box, "ListEditor.add");//$NON-NLS-1$ if ((allowButtons&ALLOW_REMOVE)==ALLOW_REMOVE) removeButton = createPushButton(box, "ListEditor.remove");//$NON-NLS-1$ if ((allowButtons&ALLOW_UP)==ALLOW_UP) upButton = createPushButton(box, "ListEditor.up");//$NON-NLS-1$ if ((allowButtons&ALLOW_DOWN)==ALLOW_DOWN) downButton = createPushButton(box, "ListEditor.down");//$NON-NLS-1$ } /** * 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 abstract String createList(String[] items); /** * 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 * @return Button */ private Button createPushButton(Composite parent, String key) { Button button = new Button(parent, SWT.PUSH); button.setText(JFaceResources.getString(key)); button.setFont(parent.getFont()); GridData data = new GridData(GridData.FILL_HORIZONTAL); int widthHint = convertHorizontalDLUsToPixels(button, IDialogConstants.BUTTON_WIDTH); data.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x); 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 == 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.verticalAlignment = GridData.FILL; gd.horizontalSpan = numColumns - 1; 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. */ private 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.marginWidth = 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) { int listStyle = SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL; if (multipleSelections) listStyle |= SWT.MULTI; else listStyle |= SWT.SINGLE; list = new List(parent, listStyle); list.setFont(parent.getFont()); list.addSelectionListener(getSelectionListener()); list.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent event) { list = null; } }); } else { checkParent(list, parent); } return list; } /** * Creates and returns a new item for the list. * <p> * Subclasses must implement this method. * </p> * * @return a new item */ protected abstract String getNewInputObject(); /* (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 */ private 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 addButton.getShell(); if (removeButton != null) return removeButton.getShell(); if (upButton != null) return upButton.getShell(); if (downButton != null) return downButton.getShell(); return null; } /** * 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 abstract String[] parseString(String stringList); /** * Notifies that the Remove button has been pressed. */ private void removePressed() { setPresentsDefaultValue(false); int [] indices = list.getSelectionIndices(); if (indices != null && indices.length != 0) { for (int i=indices.length-1; i>=0; i--) { list.remove(indices[i]); } selectionChanged(); } } /** * Notifies that the list selection has changed. */ private void selectionChanged() { int [] indices = list.getSelectionIndices(); int size = list.getItemCount(); boolean hasSelection = indices!=null && indices.length!=0; int firstSel = (hasSelection) ? indices[0] : -1; int lastSel = (hasSelection) ? indices[indices.length-1] : -1; if (removeButton != null) removeButton.setEnabled(hasSelection); if (upButton != null) upButton.setEnabled(hasSelection && size > 1 && firstSel > 0); if (downButton != null) downButton.setEnabled(hasSelection && size > 1 && lastSel < 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 */ private void swap(boolean up) { setPresentsDefaultValue(false); int [] indices = list.getSelectionIndices(); int target = up ? -1 : 1; if (indices != null && indices.length != 0) { int i = (up) ? 0 : indices.length-1; while (true) { // get and remove index String item1 = list.getItem(indices[i]); String item2 = list.getItem(indices[i] + target); // swap items list.setItem(indices[i] + target, item1); list.setItem(indices[i], item2); // adjust index and add item indices[i] += target; if ((up && i==indices.length-1) || (!up && i==0)) break; i -= target; } //adjust all the selections list.setSelection(indices); } selectionChanged(); } /** * Notifies that the Up button has been pressed. */ private void upPressed() { swap(true); } /* * @see FieldEditor.setEnabled(boolean,Composite). */ public void setEnabled(boolean enabled, Composite parent) { super.setEnabled(enabled, parent); getListControl(parent).setEnabled(enabled); if (addButton != null) addButton.setEnabled(enabled); if (removeButton != null) removeButton.setEnabled(enabled); if (upButton != null) upButton.setEnabled(enabled); if (downButton != null) downButton.setEnabled(enabled); } }
moving to JFace guys.
Susan, I'll give this to you first. Punt it back if its really a 'Preferences' issue and I'll re-assign. P.S. Congradulations!!
Brian can you attach the code as a patch file? will be easier to deal with. Thanks.
Created attachment 46729 [details] ListEditor that allows multiple items to be selected
marking 3.3 so this gets looked at... thanks, Brian.
missed the window for introducing new API. Sorry, Brian, I was on leave for a big chunk of this release and just didn't get to this in time.
changing prio and status per platform ui bug guidelines
As per http://wiki.eclipse.org/Platform_UI/Bug_Triage_Change_2009
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.