package uihelpers;
import helpers.IPrefSerializer;
import helpers.PrefConverter;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
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.Table;
import org.eclipse.swt.widgets.Widget;
import uihelpers.TableViewerAdministrator.IColumnDescriptor;
public abstract class ComplexListEditor<V> extends FieldEditor {
private Table list;
private TableViewer tableViewer;
private TableViewerAdministrator<V> tva;
private final boolean changeAllowed;
private List<V> items = new ArrayList<V>();
/**
* 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 Change Button
*/
private Button changeButton;
/**
* The selection listener.
*/
private SelectionListener selectionListener;
private final List<? extends IColumnDescriptor<V>> columns;
private final IPrefSerializer<V> translater;
private final boolean allowSorting;
/**
*
*
* @param titleText
* @param prefID
* @param columns
* @param parent - if parent is null the ComplexListEditor is created with
* no change is allowed..
*/
public ComplexListEditor(String titleText,String prefID,List<? extends IColumnDescriptor<V>> columns,
Composite parent, IPrefSerializer<V> translater) {
this(titleText,prefID,columns,parent,false,translater);
}
/**
*
*
* @param titleText - title Text
* @param prefID - the pref IS to which information will be stored
* @param columns - the columns used to create the table
* @param parent - parent widget
* @param changeAllowed - if a change Button should also be added
*/
public ComplexListEditor(String titleText,String prefID,List<? extends IColumnDescriptor<V>> columns,
Composite parent, boolean changeAllowed, IPrefSerializer<V> translater) {
this(titleText,prefID,columns,parent,changeAllowed,translater,true);
}
/**
*
*
* @param titleText - title Text
* @param prefID - the pref IS to which information will be stored
* @param columns - the columns used to create the table
* @param parent - parent widget
* @param changeAllowed - if a change Button should also be added
*/
public ComplexListEditor(String titleText,String prefID,List<? extends IColumnDescriptor<V>> columns,
Composite parent, boolean changeAllowed, IPrefSerializer<V> translater, boolean allowSorting) {
init(prefID, titleText);
this.columns = columns;
this.changeAllowed = changeAllowed;
this.translater = translater;
this.allowSorting = allowSorting;
if (parent != null) {
createControl(parent);
}
}
@Override
protected void adjustForNumColumns(int numColumns) {
Control control = getLabelControl();
((GridData) control.getLayoutData()).horizontalSpan = numColumns;
((GridData) list.getLayoutData()).horizontalSpan = numColumns - 1;
}
@Override
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);
}
/**
* Returns this field editor's list control.
*
* @param parent the parent control
* @return the list control
*/
public Table getListControl(Composite parent) {
if (list == null) {
list = new Table(parent, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL
| SWT.H_SCROLL |SWT.FULL_SELECTION);
list.setHeaderVisible(true);
tableViewer = new TableViewer(list);
tva = new TableViewerAdministrator<V>(tableViewer,columns,getPreferenceName(),Integer.MIN_VALUE,allowSorting);
tva.apply();
tableViewer.setContentProvider(new TableViewerProvider());
list.setFont(parent.getFont());
list.addSelectionListener(getSelectionListener());
list.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent event) {
list = null;
tableViewer = null;
}
});
} else {
checkParent(list, parent);
}
return list;
}
/**
* 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;
}
/**
* 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();
} else if (changeAllowed && widget == changeButton) {
changePressed();
}
}
};
}
/**
* 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;
changeButton = null;
}
});
} else {
checkParent(buttonBox, parent);
}
selectionChanged();
return buttonBox;
}
/**
* 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) {
addButton = createPushButton(box, "ListEditor.add");//$NON-NLS-1$
removeButton = createPushButton(box, "ListEditor.remove");//$NON-NLS-1$
upButton = createPushButton(box, "ListEditor.up");//$NON-NLS-1$
downButton = createPushButton(box, "ListEditor.down");//$NON-NLS-1$
if (changeAllowed) {
changeButton = createPushButton(box,"openChange"); //$NON-NLS-1$
}
}
/**
* Notifies that the Add button has been pressed.
*/
private void addPressed() {
setPresentsDefaultValue(false);
V input = getNewInputObject();
if (input != null && !items.contains(input)) {
int index = list.getSelectionIndex();
if (index >= 0) {
items.add(index+1, input);
} else {
items.add(0, input);
}
tableViewer.refresh();
selectionChanged();
}
}
@Override
protected void doLoad() {
String s = getPreferenceStore().getString(getPreferenceName());
items = PrefConverter.parseString(s,translater);
tableViewer.setInput(items);
}
@Override
protected void doLoadDefault() {
if (list != null) {
String s = getPreferenceStore().getDefaultString(
getPreferenceName());
items = PrefConverter.parseString(s,translater);
tableViewer.setInput(items);
}
}
@Override
public int getNumberOfControls() {
return 2;
}
/**
* Notifies that the list selection has changed.
*/
private 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);
if (changeAllowed) {
changeButton.setEnabled(index >= 0);
}
}
/**
* Notifies that the Up button has been pressed.
*/
private void upPressed() {
swap(true);
}
/**
* Notifies that the Down button has been pressed.
*/
private void downPressed() {
swap(false);
}
/**
* 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
*/
@SuppressWarnings("unchecked")
private void swap(boolean up) {
setPresentsDefaultValue(false);
int index = list.getSelectionIndex();
int target = up ? index - 1 : index + 1;
if (index >= 0) {
StructuredSelection sel = (StructuredSelection)tableViewer.getSelection();
V selection=(V)sel.getFirstElement();
items.remove(index);
items.add(target,selection);
tableViewer.refresh();
tableViewer.setSelection(new StructuredSelection(selection));
}
selectionChanged();
}
/**
* Notifies that the Remove button has been pressed.
*/
private void removePressed() {
setPresentsDefaultValue(false);
int index = list.getSelectionIndex();
if (index >= 0) {
items.remove(index);
tableViewer.refresh();
selectionChanged();
}
}
private void changePressed() {
setPresentsDefaultValue(false);
int index = list.getSelectionIndex();
if (index >= 0) {
V v = items.get(index);
changeInputObject(v);
tableViewer.refresh();
}
}
/* (non-Javadoc)
* Method declared on FieldEditor.
*/
protected void doStore() {
String s = PrefConverter.createList(items, translater);
if (s != null) {
getPreferenceStore().setValue(getPreferenceName(), s);
}
}
/**
* 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;
}
/*
* @see FieldEditor.setEnabled(boolean,Composite).
*/
public void setEnabled(boolean enabled, Composite parent) {
super.setEnabled(enabled, parent);
getListControl(parent).setEnabled(enabled);
addButton.setEnabled(enabled);
removeButton.setEnabled(enabled);
upButton.setEnabled(enabled);
downButton.setEnabled(enabled);
}
/* (non-Javadoc)
* Method declared on FieldEditor.
*/
public void setFocus() {
if (list != null) {
list.setFocus();
}
}
/**
* Creates and returns a new item for the list.
* <p>
* Subclasses must implement this method.
* </p>
*
* @return a new item - or null if user aborted input..
*/
protected abstract V getNewInputObject();
/**
* requests changing of some input Item
* @param v - the item that needs to be changed...
*/
protected void changeInputObject(V v) {}
class TableViewerProvider implements IStructuredContentProvider {
public void dispose() {}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
public Object[] getElements(Object inputElement) {
return ((List<?>)inputElement).toArray();
}
}
}