0

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);

}
7
  • Display.asyncExec will execute the code in the Runnable (the setImage loop) the next time the Display.runAndDispatch method is called, this will be after all the other code in the toggleSelection method is run - the table.redraw will be called first. Is that what you want? Commented Feb 6, 2024 at 9:36
  • @greg-449 I can't understand what your trying to say, actually I am new to SWT, could you please explain them in detail on how can I resolve this issue or what should I do to fix this bug, I am really confused between is this SWT's source bug or bug in my code. Please explain them in detail it would be helpful. Commented Feb 6, 2024 at 10:13
  • SWT is used by lots of things so it is not likely to be a bug in that. Once again you have shown code which is not a minimal reproducible example, since I can't run and test it I am not going to try and work out the problem. Commented Feb 6, 2024 at 10:40
  • @greg-449 Actually project is really big, we get data for this table from other part of code, so I can't send all the code here, its a open source project named DocFetcher, source code available in Github, I have implementing a new feature to it, if you would like to run and test this code you can download the project from this Github Link and Thanks for helping me out! Commented Feb 6, 2024 at 10:50
  • No, I'm not going to do that. It is up to you to make a minimal reproducible example maybe by starting with one of the simple SWT snippets such as this one and modifying it to show the problem. List of all snippets is here Commented Feb 6, 2024 at 11:46

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.