blob: 33561ff1194d396da02f9af927b77c8e3d65ef90 [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
*
* 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:
* Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
*/
package org.eclipse.osbp.preferences.ui.component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
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.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.Label;
import org.eclipse.swt.widgets.List;
/**
* A field editor for displaying and storing a list of strings.
* Buttons are provided for adding items to the list and removing
* items from the list.
*/
public class AddRemoveListFieldEditor extends FieldEditor {
private static final String TO_LEFT_SIGN = "<"; //"\u0171";
private static final String TO_RIGHT_SIGN = ">"; //"\u0187";
private static final String DEFAULT_SELECT_LABEL = TO_LEFT_SIGN+" select "+TO_LEFT_SIGN;
private static final String DEFAULT_DESELECT_LABEL = TO_RIGHT_SIGN+" deselect "+TO_RIGHT_SIGN;
private static final String DEFAULT_SEPERATOR = ";";
private static final int VERTICAL_DIALOG_UNITS_PER_CHAR = 8;
private static final int HORIZONTAL_DIALOG_UNITS_PER_CHAR = 4;
private static final int LIST_HEIGHT_IN_CHARS = 10;
private static final int LIST_HEIGHT_IN_DLUS = LIST_HEIGHT_IN_CHARS * VERTICAL_DIALOG_UNITS_PER_CHAR;
// The top-level control for the field editor.
private Composite top;
// The list of selected tags.
private List selectedList;
// The list with available and not selected tags.
private List availableList;
// The button for adding the contents of
// the available list to the selected list.
private Button select;
// The button for removing the currently-selected list item.
private Button deselect;
// The string used to seperate list items
// in a single String representation.
private String seperator = DEFAULT_SEPERATOR;
protected CLabel label;
private String[][]availableNamesAndValues;
public AddRemoveListFieldEditor(
String name,
String labelText,
String[][] availableNamesAndValues,
Composite parent) {
super(name, labelText, parent);
this.availableNamesAndValues = availableNamesAndValues;
}
public AddRemoveListFieldEditor(
String name,
String labelText,
String[][] availableNamesAndValues,
String selectButtonText,
String deselectButtonText,
Composite parent) {
this(name, labelText, availableNamesAndValues, parent);
setSelectButtonText(selectButtonText);
setDeselectButtonText(deselectButtonText);
}
public void setAvailableNamesAndValues(String[][] availableNamesAndValues) {
this.availableNamesAndValues = availableNamesAndValues;
refreshAvailableList();
}
/**
* @see org.eclipse.jface.preference.FieldEditor#adjustForNumColumns(int)
*/
protected void adjustForNumColumns(int numColumns) {
((GridData)top.getLayoutData()).horizontalSpan = numColumns;
}
/**
* @see org.eclipse.jface.preference.FieldEditor#doFillIntoGrid
* (Composite, int)
*/
protected void doFillIntoGrid(Composite parent, int numColumns) {
top = parent;
int buttonWidth = convertHorizontalDLUsToPixels(top, IDialogConstants.BUTTON_WIDTH);
int buttonHeight = convertVerticalDLUsToPixels(top, IDialogConstants.BUTTON_HEIGHT);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = numColumns;
top.setLayoutData(gd);
getLabelControl(top);
GridData labelData = new GridData();
labelData.horizontalSpan = numColumns;
label.setLayoutData(labelData);
Composite components = new Composite(top, SWT.NONE);
GridData componentsData = new GridData();
componentsData.horizontalSpan = numColumns;
componentsData.heightHint = buttonHeight * 10+10;
components.setLayoutData(componentsData);
//components.setBackground(new org.eclipse.swt.graphics.Color(components.getDisplay(), 255,255,255));
GridLayout componentsLayout = new GridLayout(3, false);
components.setLayout(componentsLayout);
selectedList = new List(components, SWT.BORDER | SWT.V_SCROLL);
GridData selectedData = new GridData();
selectedData.heightHint = buttonHeight * 10;
selectedList.setLayoutData(selectedData);
//selectedList.setBackground(new org.eclipse.swt.graphics.Color(components.getDisplay(), 255,0,0));
// Create a grid data that takes up the extra
// space in the dialog and spans both columns.
//*GridData selectedListData = new GridData(GridData.FILL_HORIZONTAL);
//*selectedListData.heightHint = convertVerticalDLUsToPixels(selectedList, LIST_HEIGHT_IN_DLUS);
//*selectedListData.horizontalSpan = numColumns;
//*selectedList.setLayoutData(selectedListData);
selectedList.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
selectedSelectionChanged();
}
});
// Create a composite for the add and remove
// buttons and the input text field.
Composite addRemoveGroup = new Composite(components, SWT.NONE);
// GridData addRemoveData = new GridData();
// addRemoveData.heightHint = buttonHeight * 10;
// addRemoveGroup.setLayoutData(addRemoveData);
//addRemoveGroup.setBackground(new org.eclipse.swt.graphics.Color(components.getDisplay(), 0,255,0));
//*GridData addRemoveData = new GridData(GridData.FILL_HORIZONTAL);
//*addRemoveData.horizontalSpan = numColumns;
//*addRemoveGroup.setLayoutData(addRemoveData);
GridLayout addRemoveLayout = new GridLayout();
addRemoveLayout.numColumns = numColumns;
addRemoveLayout.marginHeight = 0;
addRemoveLayout.marginWidth = 0;
addRemoveGroup.setLayout(addRemoveLayout);
addRemoveGroup.setSize(buttonWidth, buttonHeight*2);
// Create a composite for the add and remove buttons.
Composite buttonGroup = new Composite(addRemoveGroup, SWT.NONE);
//*buttonGroup.setLayoutData(new GridData());
GridLayout buttonLayout = new GridLayout();
buttonLayout.marginHeight = 0;
buttonLayout.marginWidth = 0;
buttonGroup.setLayout(buttonLayout);
// Create the remove button.
deselect = new Button(buttonGroup, SWT.NONE);
deselect.setEnabled(false);
deselect.setText(DEFAULT_DESELECT_LABEL);
deselect.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
deselect();
showDefaultHint();
}
});
GridData removeData = new GridData(GridData.FILL_HORIZONTAL);
removeData.heightHint = buttonHeight;
removeData.widthHint = buttonWidth;
deselect.setLayoutData(removeData);
// Create the add button.
select = new Button(buttonGroup, SWT.NONE);
select.setEnabled(false);
select.setText(DEFAULT_SELECT_LABEL);
select.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
select();
showDefaultHint();
}
});
GridData addData = new GridData(GridData.FILL_HORIZONTAL);
addData.heightHint = buttonHeight;
addData.widthHint = buttonWidth;
select.setLayoutData(addData);
// available list
availableList = new List(components, SWT.BORDER | SWT.V_SCROLL);
GridData availableData = new GridData();
availableData.heightHint = buttonHeight * 10;
availableList.setLayoutData(availableData);
//availableList.setBackground(new org.eclipse.swt.graphics.Color(components.getDisplay(), 0,0,255));
// Create a grid data that takes up the extra
// space in the dialog and spans both columns.
//*GridData availableListData = new GridData(GridData.FILL_HORIZONTAL);
//*availableListData.heightHint = convertVerticalDLUsToPixels(availableList, LIST_HEIGHT_IN_DLUS);
//*availableListData.horizontalSpan = numColumns;
//*availableList.setLayoutData(availableListData);
availableList.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
availableSelectionChanged();
}
});
}
protected void showDefaultHint() {
String defaults = getPreferenceStore().getDefaultString(getPreferenceName());
String selected = createListString(selectedList.getItems());
APreferencePage.showLabelDefaultHint(label, defaults.equals(selected));
}
@Override
public Label getLabelControl(Composite parent) {
if (label == null) {
label = new CLabel(parent, SWT.LEFT | SWT.RIGHT_TO_LEFT);
label.setFont(parent.getFont());
String text = getLabelText();
if (text != null) {
label.setText(text);
}
label.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent event) {
label = null;
}
});
} else {
checkParent(label, parent);
}
return null;
}
@Override
public void setEnabled(boolean enabled, Composite parent) {
label.setEnabled(enabled);
}
/**
* @see org.eclipse.jface.preference.FieldEditor#doLoad()
*/
protected void doLoad() {
String items = getPreferenceStore().getString(getPreferenceName());
setList(items);
showDefaultHint();
}
/**
* @see org.eclipse.jface.preference.FieldEditor#doLoadDefault()
*/
protected void doLoadDefault() {
String items = getPreferenceStore().getDefaultString(getPreferenceName());
setList(items);
showDefaultHint();
}
// Parses the string into seperate list items and adds them to the list.
private void setList(String items) {
String[] itemArray = parseString(items);
selectedList.setItems(itemArray);
}
/**
* @see org.eclipse.jface.preference.FieldEditor#doStore()
*/
protected void doStore() {
String s = createListString(selectedList.getItems());
if (s != null)
getPreferenceStore().setValue(getPreferenceName(), s);
}
/**
* @see org.eclipse.jface.preference.FieldEditor#getNumberOfControls()
*/
public int getNumberOfControls() {
// The button composite and the text field.
return 2;
}
// Adds the string in the text field to the list.
private void select() {
Set<String> items = new TreeSet<String>();
items.addAll(Arrays.asList(selectedList.getItems()));
items.addAll(Arrays.asList(availableList.getSelection()));
selectedList.removeAll();
for (String addItem : items) {
selectedList.add(addItem);
}
refreshAvailableList();
}
private void deselect() {
Set<String> items = new TreeSet<String>();
items.addAll(Arrays.asList(selectedList.getItems()));
items.removeAll(Arrays.asList(selectedList.getSelection()));
selectedList.removeAll();
for (String addItem : items) {
selectedList.add(addItem);
}
refreshAvailableList();
}
private void refreshAvailableList() {
java.util.List<String> ignoreItems = Arrays.asList(selectedList.getItems());
availableList.removeAll();
for (int idx = 0; idx < availableNamesAndValues.length; idx++) {
String addItem = availableNamesAndValues[idx][1];
if ((addItem != null) && !ignoreItems.contains(addItem)) {
availableList.add(addItem);
}
}
selectedList.deselectAll();
availableList.deselectAll();
select.setEnabled(false);
deselect.setEnabled(false);
}
/**
* Sets the label for the button that adds
* the contents of the text field to the list.
*/
public void setSelectButtonText(String text) {
select.setText(text);
}
/**
* Sets the label for the button that removes
* the selected item from the list.
*/
public void setDeselectButtonText(String text) {
deselect.setText(text);
}
/**
* Sets the string that seperates items in the list when the
* list is stored as a single String in the preference store.
*/
public void setSeperator(String seperator) {
this.seperator = seperator;
}
/**
* Creates the single String representation of the list
* that is stored in the preference store.
*/
private String createListString(String[] items) {
StringBuffer path = new StringBuffer("");//$NON-NLS-1$
for (int i = 0; i < items.length; i++) {
if (i > 0) {
path.append(seperator);
}
path.append(items[i]);
}
return path.toString();
}
/**
* Parses the single String representation of the list
* into an array of list items.
*/
private String[] parseString(String stringList) {
StringTokenizer st =
new StringTokenizer(stringList, seperator); //$NON-NLS-1$
ArrayList v = new ArrayList();
while (st.hasMoreElements()) {
v.add(st.nextElement());
}
return (String[])v.toArray(new String[v.size()]);
}
// Sets the enablement of the remove button depending
// on the selection in the list.
private void selectedSelectionChanged() {
int index = selectedList.getSelectionIndex();
deselect.setEnabled(index >= 0);
availableList.deselectAll();
select.setEnabled(false);
}
// Sets the enablement of the remove button depending
// on the selection in the list.
private void availableSelectionChanged() {
int index = availableList.getSelectionIndex();
select.setEnabled(index >= 0);
selectedList.deselectAll();
deselect.setEnabled(false);
}
}