Community
Participate
Working Groups
Resorting a tableviewer (using refresh) does not update the images of cells which have the same text value. For example, let's say I have a table with only 1 column and 4 rows. Each cell holds the same text value, and the top two I define to have images. If I perform a refresh and the ViewerSorter shuffles the top two cells to the bottom, visually the user should see the top two cells without images and the bottom two with. However in actuality, all four appear to have images. If the window is hidden and then opened again, the images appear correctly. Selecting arow also correctly refreshes the image area for all the cells in that row. I am pasting a code sample of this below. To recreate this bug, click the 2nd column header to resort the 2nd column. ============================================================================== import java.util.ArrayList; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.jface.window.ApplicationWindow; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; /** * This class demonstrates TableViewers - demonstrates how images in cells don't * get updated upon sorting (if no value) */ public class TableViewerSortBugExample extends ApplicationWindow { private ArrayList myModel; private TableViewer myTableViewer; private Image myCellImage = null; /** * Constructs a PlayerTable */ public TableViewerSortBugExample () { super(null); myModel = initModel(); } /** * Runs the application */ public void run () { setBlockOnOpen(true); open(); Display.getCurrent().dispose(); } /** * Configures the shell * * @param shell the shell */ protected void configureShell (Shell shell) { super.configureShell(shell); shell.setSize(400, 400); } /** * Creates the main window's contents * * @param parent the main window * @return Control */ protected Control createContents (Composite parent) { // Create the composite to hold the controls Composite composite = new Composite(parent, SWT.NONE); composite.setLayout(new GridLayout(1, false)); // Create the table viewer to display the players myTableViewer = new TableViewer(composite, SWT.FULL_SELECTION); // Set the content and label providers myTableViewer.setContentProvider(getContentProvider()); myTableViewer.setLabelProvider(getLabelProvider()); myTableViewer.setSorter(new MyTableSorter()); // Set up the table Table table = myTableViewer.getTable(); table.setLayoutData(new GridData(GridData.FILL_BOTH)); // A Column TableColumn tc = new TableColumn(table, SWT.RIGHT); tc.setText("A Column"); // A second column tc = new TableColumn(table, SWT.RIGHT); tc.setText("B Column"); tc.addSelectionListener(new SelectionAdapter() { public void widgetSelected (SelectionEvent event) { ((MyTableSorter)myTableViewer.getSorter()).toggleAscending(); myTableViewer.refresh(); } }); // Pack the columns for (int i = 0, n = table.getColumnCount(); i < n; i++) { table.getColumn(i).pack(); } // Turn on the header and the lines myTableViewer.setInput(myModel); table.setHeaderVisible(true); table.setLinesVisible(true); return composite; } /** * The application entry point * * @param args the command line arguments */ public static void main (String[] args) { new TableViewerSortBugExample().run(); } /** * Initialize the model */ private ArrayList initModel () { ArrayList model = new ArrayList(); for (int i=0; i<4; i++) { Cell newCell = new Cell(); newCell.text = "a"; if (i==0 || i==1 ) { newCell.hasImage = true; } model.add(newCell); } return model; } /** * Get the content provider * * @return content provider */ private IStructuredContentProvider getContentProvider() { return new IStructuredContentProvider() { public Object[] getElements (Object inputElement) { return ((ArrayList)inputElement).toArray(); } public void dispose () {} public void inputChanged (Viewer viewer, Object oldInput, Object newInput) {} }; } private ITableLabelProvider getLabelProvider () { return new ITableLabelProvider() { public Image getColumnImage (Object element, int columnIndex) { if (columnIndex == 1) { if (((Cell)element).hasImage) { return getImage(); } } return null; } public String getColumnText (Object element, int columnIndex) { if (columnIndex == 0) { return "empty"; } return ((Cell)element).text; } public void addListener (ILabelProviderListener listener) {} public void dispose () { } public boolean isLabelProperty (Object element, String property) { return false; } public void removeListener (ILabelProviderListener listener) { } }; } /** * Get the image for a cell */ private Image getImage () { if (myCellImage == null) { int xSize = 16; int ySize = 16; Display currentDisplay = Display.getCurrent(); myCellImage = new Image (currentDisplay, xSize, ySize); GC gcImage = new GC(myCellImage); // set background color Color bgColor = currentDisplay.getSystemColor(SWT.COLOR_YELLOW); gcImage.setBackground(bgColor); gcImage.fillRectangle(0, 0, 16, 16); gcImage.dispose(); } return myCellImage; } // --------------------------- INTERNAL CLASSES --------------------------------- /** * Cell contents */ private class Cell { public boolean hasImage; public String text; } private class MyTableSorter extends ViewerSorter { private boolean myIsAscending = true; public int compare(Viewer viewer, Object e1, Object e2) { Cell cell1 = (Cell)e1; Cell cell2 = (Cell)e2; int result = 0; if (cell1.hasImage && !cell2.hasImage) result = 1; else if (!cell1.hasImage && cell2.hasImage) result = -1; if (!myIsAscending) { result = -1*result; } return result; } public void toggleAscending () { myIsAscending = !myIsAscending; } } }
Seems to work in 3.3.