Tuesday, August 03, 2010

SWT Table: row header

I always used the SWT Table as grid component for my project Matrex.
The problem of this grid component is that it does not have a row header; and this is a real problem for an application like Matrex, that is an alternative to spreadsheet applications.
There are alternatives to the SWT Table that have a row header, but even if some of them are very good I personally prefer to use the original SWT Table.
So I tried the fixed first column horizontal scroll remaining columns SWT snippet, where the row header consists in a second SWT Table with only one column, syncronized with the main table.
This solution works fine in Windows, but has the following disadvantages:
  • In Gnome/Linux scrolling the table up and down the first row can be partially hidden by the column header. This is not handled by the snippet, therefore from time to time the row header appears not synchronized with the table.
  • The cells of the row header table are normal cells, not header cells (3D gray-button look). This can be fixed, but it looks like for a table of 10000 rows you need to create 10000 buttons!
So I have found a different solution, which uses a separate control for the row header, like in the snippet.
The row header control is a panel containing a vertical set of buttons, one for each visible row of the table.
You can see the panel on the left in the following picture (which is based on the SWT snippet create a table (columns, headers, lines)) :


In the picture, each button shows the index of the related row.
When the user scrolls the table vertically, the buttons texts change accordingly.
If part of the row is partially hidden by the column header, like in the picture, the related button is also partially hidden.
If the horizontal scrollbar appears, the row header changes its size accordingly.
In synthesis, the row header is always synchronized with the table.

You can see a demo of the row header in this video.

The table row header is just a single class, that can be tested using this test class.

The only complicated part of the class is the function getOffset, which solves the problem of the "partially hidden first row", returning the part of the first row that is hidden.
It uses the SWT Table function table.getItem([point]), which returns the row at the given point.
With this function it can know where is the limit between the first and second row, and therefore when the first row finishes. Knowing the height of each row (table.getItemHeigh), it calculates which part of the row is hidden.

I tested it with Windows and Linux (Ubuntu) and it works fine. It could be nice if someone can test it on MacOSX. There should be no problem, since it uses only documented functions in a standard way.
I will use it on all tables of the Matrex project.