Search code examples
javaeclipse-pluginswtjfacetableviewer

How to filter the inputs in Table with SWT.Virtual?


In my project, I have a TableViewer which needs to show around 3000 items and also filter them. Without SWT.VIRTUAL the table takes multiple seconds to display.
So, I implemented ILazyContentProvider and not using "ArrayContentProvider" but now I am facing issues in filtering the elements of TableViewer.

I am writing the below code for filtering but the select method is not running at all.

   private static class DefaultFilterextends ViewerFilter {
    
            private String searchText;
    
            public void setSearchText(final String searchText) {
                this.searchText = searchText;
            }
    
            @Override
            public boolean select(Viewer viewer, Object parentElement, Object element) {
                if (this.searchText == null) {
                    return true;
                }
                return (element.toString().contains(searchText) || element.toString().equals(searchText));
            }
    }

The below ContentProvider, I am writting

  private class LazyContentProvider implements ILazyContentProvider {

        private TableViewer viewer;
        private List<String> elements;

        public LazyContentProvider(TableViewer viewer) {
            this.viewer = viewer;
        }

        @Override
        public void dispose() {
        }

        @Override
        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            this.elements = (List<String>) newInput;
        }

        @Override
        public void updateElement(int index) {
            viewer.replace(elements.get(index), index);
        }

    }

Can someone please guide me how can I do the filteration of elements in TableViewer with SWT.VIRTUAL?


Solution

  • TableViewer does not support filtering when SWT.VIRTUAL is used. Instead you must do the filtering in the content provider.

    The content provider will need to maintain a filtered list of elements. For example:

    public class LazyContentProvider implements ILazyContentProvider
    {
      private TableViewer viewer;
      private List<String> allElements;
      private List<String> filteredElements;
    
    
      public LazyContentProvider()
      {
        //
      }
    
    
      @Override
      public void dispose()
      {
        //
      }
    
    
      @SuppressWarnings("unchecked")
      @Override
      public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput)
      {
        this.viewer = (TableViewer)viewer;
    
        allElements = (List<String>)newInput;
    
        filteredElements = allElements;
      }
    
    
      @Override
      public void updateElement(final int index)
      {
        viewer.replace(filteredElements.get(index), index);
      }
    
    
      public void filter(final String searchText)
      {
        filteredElements = allElements.stream().filter(element -> element.contains(searchText)).toList();
    
        viewer.setItemCount(filteredElements.size());
    
        viewer.refresh();
      }
    }
    

    Here I have added a filteredElements list that contains just the current filtered elements, this is used in updateElement.

    I added a filter method which updates the filtered elements list. It also tells the table viewer about the new item count and refreshes the table.

    The .toList() method in the filter stream requires Java 16, for older versions of Java use .collect(Collectors.toList()).