Monday, April 18, 2011

Detecting change in SWT Table's scrollbar visibility

Recently on stackoverflow there was a question asked related to this. The requirement was simple ‘resize all the columns as soon as scrollbar appears or disappears’. Now, if you look deep into the SWT table API then you will notice that there is no direct solution for this because:
  1. There is no way to get the scrollbar handle
  2. Scrollbar does not support any event related to visibility
One can solve this problem by implementing a simple hack. I am using the concept presented in this SWT snippet compute the visible rows in a table. Along with that I am also using SWT Paint Event.

The basic concept is as follows:
  1. Calculate the number of visible rows (items).
  2. Compare it with total number of rows (items).
  3. Do all this in some event which occurs with the addition of rows (items). I have chosen the SWT Paint Event
>> Code
import org.eclipse.swt.*;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class TableScrollVisibilityTest 
{
    private static int count;

    public static void main(String [] args) 
    {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setBounds(10,10,300,300);
        shell.setLayout(new GridLayout(2,true));

        final Table table = new Table(shell, SWT.NONE);
        GridData data = new GridData(GridData.FILL_BOTH);
        data.horizontalSpan = 2;
        table.setLayoutData(data);

        count = 0;

        final Button addItem = new Button (shell, SWT.PUSH);
        addItem.setText ("Add Row");
        data = new GridData(SWT.FILL, SWT.FILL, true, false);
        data.horizontalSpan = 2;
        addItem.setLayoutData(data);

        final Text text = new Text(shell, SWT.BORDER);
        text.setText ("Vertical Scroll Visible - ");
        data = new GridData(SWT.FILL, SWT.FILL, true, false);
        data.horizontalSpan = 2;
        text.setLayoutData(data);


        addItem.addListener (SWT.Selection, new Listener () 
        {
            public void handleEvent (Event e) 
            {
                new TableItem(table, SWT.NONE).setText("item " + count);
                count++;
            }
        });


        table.addPaintListener(new PaintListener() {
            public void paintControl(PaintEvent e) {
                Rectangle rect = table.getClientArea ();
                int itemHeight = table.getItemHeight ();
                int headerHeight = table.getHeaderHeight ();
                int visibleCount = (rect.height - headerHeight + itemHeight - 1) / itemHeight;
                text.setText ("Vertical Scroll Visible - [" + (table.getItemCount()>= visibleCount)+"]");

                      // YOUR CODE HERE
            }
        });


        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }

        display.dispose();
    }

}

>> Output
For itemcount < numberofvisible rows


For itemcount >= numberofvisible rows


Note - If you are going to use the paint event then try keep the calculations minimum as it is called frequently.

No comments:

Post a Comment