Bug 111499 - [Viewers] TableViewer does not redraw images in cells with same text value after sort
Summary: [Viewers] TableViewer does not redraw images in cells with same text value af...
Status: RESOLVED WORKSFORME
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 normal with 1 vote (vote)
Target Milestone: ---   Edit
Assignee: Boris Bokowski CLA
QA Contact:
URL:
Whiteboard:
Keywords: investigate
Depends on:
Blocks:
 
Reported: 2005-10-04 14:47 EDT by Darren Lew CLA
Modified: 2007-06-26 13:29 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Darren Lew CLA 2005-10-04 14:47:16 EDT
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;
        }
    }
}
Comment 1 Boris Bokowski CLA 2007-06-26 13:29:05 EDT
Seems to work in 3.3.