I have a application which has virtual table, in that table when user search for a keyword and it shows list of available document that match that keyword in that table. When user click the header of 1st column it select all the checkbox item in the 1st column, now the issue is after selecting all the check box, and when I tried to scroll through the table, only the items which was visible during the click action of select all was visible in the table, other items are not visible. But it has actual item when I click that empty space it shows detail about the document.
As I tried debugging the code, when table.redraw() called it should need to redraw the entire table but in my case it doesn't.
This is the function where I called redraw():
private void toggleSelection() {
Display.getDefault().asyncExec(() -> {
for (TableItem item : table.getItems()) {
item.setImage(0, isAllSelected ? Img.CHECKBOX_CHECKED.get() : Img.CHECKBOX_UNCHECKED.get());
}
table.redraw();
});
List<ResultDocument> selectedItems = new ArrayList<>();
for (TableItem item : table.getItems()) {
if (isAllSelected) {
selectedItems.add((ResultDocument) item.getData());
}
}
ResultPanel.selDocument.clear();
ResultPanel.selDocument.addAll(selectedItems);
}
This is my constructor where I initialize listener:
public VirtualTableViewer(@NotNull Composite parent, int style) {
table = new Table(parent, style | SWT.VIRTUAL);
table.setHeaderVisible(true);
table.addListener(SWT.SetData, new Listener() {
public void handleEvent(org.eclipse.swt.widgets.Event event) {
// Bug #3523251: event.index can be -1 sometimes, looks like a
// bug in SWT.
// Bug #1298 and others: Sometimes event.index == elements.size().
if (event.index < 0 || event.index >= elements.size())
return;
Util.checkThat(!columns.isEmpty());
TableItem item = (TableItem) event.item;
E element = elements.get(event.index);
for (int iCol = 0; iCol < columns.size(); iCol++) {
Column<E> column = columns.get(iCol);
item.setText(iCol, column.getLabel(element));
item.setImage(iCol, column.getImage(element));
item.setForeground(iCol, column.getForeground(element));
item.setBackground(iCol, column.getBackground(element));
}
item.setData(element);
}
});
}
This is my full code for VirtualTableViewer class:
public abstract class VirtualTableViewer<E> {
public static abstract class Column<E> {
private String label;
private final int orientation;
private final Event<String> evtLabelChanged = new Event<String> ();
private int lastSortDirection = 1;
public Column(@NotNull String label) {
this(label, SWT.LEFT);
}
public Column(@NotNull String label, int orientation) {
this.label = Util.checkNotNull(label);
this.orientation = orientation;
}
@NotNull
public final String getLabel() {
return label;
}
public final void setLabel(@NotNull String label) {
Util.checkNotNull(label);
if (this.label.equals(label)) return;
this.label = label;
evtLabelChanged.fire(label);
}
@NotNull protected abstract String getLabel(E element);
@Nullable protected String getToolTipText() { return null; }
@Nullable protected Image getImage(E element) { return null; }
@Nullable protected Color getForeground(E element) { return null; }
@Nullable protected Color getBackground(E element) { return null; }
protected int compare(@NotNull E e1, @NotNull E e2) { return 0; }
}
private boolean isAllSelected = false;
private final Table table;
private final List<Column<E>> columns = new ArrayList<Column<E>>();
private List<E> elements;
private boolean sortingEnabled = false;
@Nullable private Column<E> lastSortColumn = null;
public VirtualTableViewer(@NotNull Composite parent, int style) {
table = new Table(parent, style | SWT.VIRTUAL);
table.setHeaderVisible(true);
table.addListener(SWT.SetData, new Listener() {
public void handleEvent(org.eclipse.swt.widgets.Event event) {
// Bug #3523251: event.index can be -1 sometimes, looks like a
// bug in SWT.
// Bug #1298 and others: Sometimes event.index == elements.size().
if (event.index < 0 || event.index >= elements.size())
return;
Util.checkThat(!columns.isEmpty());
TableItem item = (TableItem) event.item;
E element = elements.get(event.index);
for (int iCol = 0; iCol < columns.size(); iCol++) {
Column<E> column = columns.get(iCol);
item.setText(iCol, column.getLabel(element));
item.setImage(iCol, column.getImage(element));
item.setForeground(iCol, column.getForeground(element));
item.setBackground(iCol, column.getBackground(element));
}
item.setData(element);
}
});
}
@NotNull
public final Table getControl() {
return table;
}
public final void addColumn(@NotNull final Column<E> column, boolean isSelectColumn) {
Util.checkNotNull(column);
columns.add(column);
final TableColumn tableColumn = new TableColumn(table, column.orientation);
tableColumn.setText(column.label);
tableColumn.setToolTipText(column.getToolTipText());
column.evtLabelChanged.add(new Event.Listener<String>() {
public void update(String eventData) {
tableColumn.setText(eventData);
}
});
if (isSelectColumn) {
tableColumn.setImage(Img.CHECKBOX_UNCHECKED.get());
tableColumn.addListener(SWT.Selection, event -> {
if (tableColumn.getImage() == Img.CHECKBOX_UNCHECKED.get()) {
tableColumn.setImage(Img.CHECKBOX_CHECKED.get());
isAllSelected = true;
} else {
tableColumn.setImage(Img.CHECKBOX_UNCHECKED.get());
isAllSelected = false;
}
toggleSelection();
});
}
}
private void toggleSelection() {
Display.getDefault().asyncExec(() -> {
for (TableItem item : table.getItems()) {
item.setImage(0, isAllSelected ? Img.CHECKBOX_CHECKED.get() : Img.CHECKBOX_UNCHECKED.get());
}
table.redraw();
});
List<ResultDocument> selectedItems = new ArrayList<>();
for (TableItem item : table.getItems()) {
if (isAllSelected) {
selectedItems.add((ResultDocument) item.getData());
}
}
ResultPanel.selDocument.clear();
ResultPanel.selDocument.addAll(selectedItems);
}
public final void sortByColumn(@NotNull final Column<E> column) {
if (elements == null || !sortingEnabled)
return;
final int direction = lastSortColumn != column
? 1
: column.lastSortDirection * -1;
Collections.sort(elements, new Comparator<E>() {
public int compare(E e1, E e2) {
return column.compare(e1, e2) * direction;
};
});
table.clearAll();
lastSortColumn = column;
column.lastSortDirection = direction;
}
public final void sortByColumn(@NotNull final Column<E> column, boolean up) {
if (elements == null || !sortingEnabled)
return;
final int direction = up ? 1 : -1;
Collections.sort(elements, new Comparator<E>() {
public int compare(E e1, E e2) {
return column.compare(e1, e2) * direction;
};
});
table.clearAll();
lastSortColumn = column;
column.lastSortDirection = direction;
}
@Immutable
@NotNull
public final List<Column<E>> getColumns() {
return Collections.unmodifiableList(columns);
}
@Immutable
@NotNull
public final List<Column<E>> getColumnsVisualOrder() {
List<Column<E>> visualColumns = new ArrayList<Column<E>>(columns.size());
for (int index : table.getColumnOrder())
visualColumns.add(columns.get(index));
return Collections.unmodifiableList(visualColumns);
}
// does not take sorting into account
public final void setRoot(@NotNull Object rootElement) {
Util.checkNotNull(rootElement);
Util.checkThat(!columns.isEmpty());
elements = Util.checkNotNull(getElements(rootElement));
table.setItemCount(elements.size()); // Must be called *before* calling clearAll()
table.clearAll();
lastSortColumn = null;
}
@MutableCopy
@NotNull
public final List<E> getSelection() {
/* Note that we must use table.getSelectionIndices here, rather than
* table.getSelection, since on a virtual table some TableItems may
* still be uninitialized. */
int[] selIndices = table.getSelectionIndices();
List<E> selElements = new ArrayList<E>(selIndices.length);
for (int index : selIndices) {
selElements.add(elements.get(index));
}
return selElements;
}
public final void scrollToTop() {
ScrollBar verticalBar = table.getVerticalBar();
if (verticalBar != null)
verticalBar.setSelection(0);
}
public final void scrollToBottom() {
TableItem lastItem = table.getItem(table.getItemCount() - 1);
table.showItem(lastItem);
}
// when sorting is enabled, override the compare method on all sortable columns
public void setSortingEnabled(boolean sortingEnabled) {
this.sortingEnabled = sortingEnabled;
if (!sortingEnabled)
lastSortColumn = null;
}
@NotNull
protected abstract List<E> getElements(@NotNull Object rootElement);
}