Sunday, August 27, 2006

Virtual tables

In version 1.0 RC1 I used a feature of the SWT library, the virtual tables (SWT.VIRTUAL), in the matrix viewer.
This feature allows to show in the matrix viewer a matrix of thousand of rows and columns with a very good performance.
The idea is simple: since a table shows only a few rows at a time, you don't need to load the whole matrix in the table in one shot; you need to load only the rows that are shown in that moment.

My plan is to use the same feature also in the presentation viewer in a future version of the system (1.0 RC2?).

In this entry, I wanted to explain how I used the virtual tables in the matrix viewer.
For the implementation you can look in the CVS tree for the classes:

  • matrex.gui.viewer.matrix.MatrixViewer, the viewer

  • matrex.gui.viewer.matrix.MatrixViewerCache the cache for the viewer, containing the current version of the matrix (in other words, the viewer's model)



I based my code on the article SWT - Virtual Tables Tutorial.
As in the tutorial, I use the SWT.SetData event to fill the rows of the table. When the table shows a new row, it triggers a SWT.SetData event; in this event the code fills the row with data.
Differently from the tutorial, the matrix showed in the table can change its content at any time, and when this happens the table content must be updated.

Each time the matrix is updated, the code checks how big is the change, examining a small sample of items of the matrix:

  1. if only a small amount of items of the matrix is changed, only those items in the viewer need to be changed.

    Doing some test I discovered that extracting a row that the table did not show, using the statement table.getItem, the row is not null but each of its item is empty and the table does not try to populate it triggering a SWT.SetData event.
    Therefore it does not make sense to update a row that was not shown before.

    So, the viewer cache keeps an array that tells for each row if the row was shown before (for which an SWT.SetData event has been triggered).
    When an item of a row needs to be updated:


    • If the row was shown before it is updated immediately using the table.getItem.setText statement.

    • Otherwise nothing is done: if the table later shows the row, it triggers the SWT.SetData event for that row, which reads its current, updated content from the cache.



  2. Otherwise the table is cleared and filled up again with the new matrix; as we saw in this case the performances are good because the only rows that are loaded are the ones that are shown.
    To clear the table I used the following statements:

    table.clearAll();
    table.redraw();
    table.setItemCount([number of rows of the matrix]);

    The last statement triggers the SWT.SetData events for the shown rows.



I tested this solution with small and big matrices, small and big changes and it seems to work correctly and with good performances.

1 comment:

Andrew Selivanov said...

item = table.getItem(y); table.setSelection(item);