I'm pretty sure what I'm asking is impossible, but I couldn't find a definitive no to the question anywhere, so here it goes:
Consider the following working example:
public class TableViewerSorter {
private static final String DATA_COMPARATOR = "comparator";
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final TableViewer viewer = new TableViewer(shell, SWT.BORDER);
Table table = viewer.getTable();
table.setHeaderVisible(true);
viewer.setContentProvider(ArrayContentProvider.getInstance());
viewer.setSorter(new ViewerSorter() {
@Override
public int compare(Viewer v, Object e1, Object e2) {
TableColumn sortColumn = table.getSortColumn();
Comparator comparator = sortColumn == null ? null : (Comparator) sortColumn.getData(DATA_COMPARATOR);
if (comparator != null && table.getSortDirection() == SWT.UP) {
comparator = comparator.reversed();
}
return comparator == null ? 0 : comparator.compare(e1, e2);
}
});
createTableViewerColumn(viewer, "ID", v -> v.ordinal());
createTableViewerColumn(viewer, "Name", v -> v.getDisplayName());
createTableViewerColumn(viewer, "Fruit", v -> v.isFruit());
for (TableColumn column : table.getColumns()) {
column.addListener(SWT.Selection, e -> {
final Item sortColumn = table.getSortColumn();
int direction = table.getSortDirection();
if (column.equals(sortColumn)) {
direction = direction == SWT.UP ? SWT.DOWN : SWT.UP;
} else {
table.setSortColumn(column);
direction = SWT.UP;
}
table.setSortDirection(direction);
viewer.refresh();
});
}
viewer.setInput(Value.values());
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
private static <T extends Comparable<T>> TableViewerColumn createTableViewerColumn(TableViewer viewer, String name,
Function<Value, T> propertyFunction) {
TableViewerColumn viewerColumn = new TableViewerColumn(viewer, SWT.NONE);
viewerColumn.setLabelProvider(new ColumnLabelProvider() {
@Override
public String getText(Object element) {
return propertyFunction.apply((Value) element).toString();
}
});
TableColumn column = viewerColumn.getColumn();
column.setText(name);
column.setWidth(100);
column.setData(DATA_COMPARATOR, (Comparator<Value>) (v1, v2) -> propertyFunction.apply(v1).compareTo(propertyFunction.apply(v2)));
return viewerColumn;
}
static enum Value {
APPLE, BANANA, CABBAGE, DILL, EGGPLANT;
String getDisplayName() {
return name().substring(0, 1) + name().substring(1).toLowerCase();
}
boolean isFruit() {
return this != CABBAGE && this != DILL;
}
}
static class LabelProvider<T> extends ColumnLabelProvider {
private final Function<T, String> toStringFunction;
public LabelProvider(final Function<T, String> toStringFunction) {
this.toStringFunction = toStringFunction;
}
@Override
public String getText(final Object element) {
return element == null ? null : this.toStringFunction.apply((T) element);
}
}
}
What I want is for the user to click the second column then the third, and have the input sorted by the third column, and when the values are equal, by the second.
Of course I can just add a list of clicked columns to the ViewerSorter
, or (depending on the sorting algorithm) just use the last sorted list of elements as a base for sorting instead of the viewer's input.
That's the easy part.
The hard part is how to communicate to the user that this particular table is sorted by two columns. The API seems to not support the use case, but I want to make sure: Is it possible for JFace tables to be sorted by multiple columns? If so, how?
Select a cell in the column you want to sort. On the Data tab, in the Sort & Filter group, click Sort. In the Sort dialog box, under Column, in the Sort by or Then by box, select the column that you want to sort by a custom list.
There is currently no standard way to indicate multiple sort columns. There is a long standing bug 133154 requesting support for multiple setSortColumm
columns but nothing has ever been done.
Yes. greg-449 is correct that there is no standard implementation so far. If you are really keen on some how get it working, I have a workaround by using TableColumn.setImage(image)
,set correct sort image on column . Maintain sort order in TableColumn.setData(key,value)
and all sorted columns in Table.setData(key,value)
and never use or set Table.setSortDirection(direction)
and Table.setSortColumn().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With