You do not need use the JFace Databinding Framework in TableViewer. Manipulation the structured data is simpler then swt controls, such TableViewer, ListViewer and TreeViewer. You can use those viewer in the same way:
- create viewer
- set content provider
- set label provider (suggested)
- set filter (optional)
- set sorter (optional)
After the viewer created, just invoke viewer.setInput(data) to put all the things to your viewer.
There are a list of Model:
TableViewer tableViewer = new TableViewer(parent);
Table table = tableViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);`
for (int i = 0; i < COLUMN_NAMES.length; i++) {
TableColumn tableColumn = new TableColumn(table, SWT.LEFT);
tableColumn.setText(COLUMN_NAMES[i]);
tableColumn.setWidth(COLUMN_WIDTHS[i]);
}
tableViewer.setContentProvider(new ModelContentProvider());
tableViewer.setLabelProvider(new ModelLabelProvider());
tableViewer.setInput(models);
The magic happens in the content provider:
class ModelContentProvider implements IStructuredContentProvider {
@SuppressWarnings("unchecked")
@Override
public Object[] getElements(Object inputElement) {
// The inputElement comes from view.setInput()
if (inputElement instanceof List) {
List models = (List) inputElement;
return models.toArray();
}
return new Object[0];
}
/* ... other methods */
}
Each model will become a TableItem and the model in the TableItem(item.getData()).
However, a table composed by many columns, you need the LabelProvider to help you mapping the property of Model to the TableItem:
class ModelLabelProvider extends LabelProvider implements
ITableLabelProvider {
@Override
public Image getColumnImage(Object element, int columnIndex) {
// no image to show
return null;
}
@Override
public String getColumnText(Object element, int columnIndex) {
// each element comes from the ContentProvider.getElements(Object)
if (!(element instanceof Model)) {
return "";
}
Model model = (Model) element;
switch (columnIndex) {
case 0:
return model.getFoo();
case 1:
return model.getBar();
default:
break;
}
return "";
}
}
The propagation of models to viewer is easy. If you will propagate viewer to the binded model, using the CellEditor is simple as well.
To use CellEditor, you need set the column properties, celleditors and cell modifier to TableViewer:
tableViewer.setColumnProperties(COLUMNS_PROPERTIES);
tableViewer.setCellEditors(new CellEditor[] {
new TextCellEditor(table), new TextCellEditor(table) });
tableViewer.setCellModifier(new ModelCellModifier(tableViewer));
The CellModifier likes this:
class ModelCellModifier implements ICellModifier {
TableViewer viewer;
public ModelCellModifier(TableViewer viewer) {
this.viewer = viewer;
}
@Override
public boolean canModify(Object element, String property) {
// property is defined by viewer.setColumnProperties()
// allow the FOO column can be modified.
return "foo_prop".equals(property);
}
@Override
public Object getValue(Object element, String property) {
if ("foo_prop".equals(property)) {
return ((Model) element).getFoo();
}
if ("bar_prop".equals(property)) {
return ((Model) element).getBar();
}
return "";
}
@Override
public void modify(Object element, String property, Object value) {
if ("foo_prop".equals(property)) {
TableItem item = (TableItem) element;
((Model) item.getData()).setFoo("" + value);
// refresh the viewer to show the changes to our user.
viewer.refresh();
}
}
}
Everything is simple but there are many steps to make all together.