TS-4706 Bringing JTable to the Extreme

Preview:

DESCRIPTION

TS-4706 Bringing JTable to the Extreme. David Qiao JIDE Software, Inc. About JIDE. JIDE Software is a Swing component provider Over 12 different products Also provide L&F, UI and icon design service JIDE Docking Framework JIDE Grids JIDE Pivot Grid JIDE Data Grids - PowerPoint PPT Presentation

Citation preview

TS-4706 Bringing JTable to the ExtremeDavid QiaoJIDE Software, Inc.

About JIDE> JIDE Software is a Swing component provider> Over 12 different products> Also provide L&F, UI and icon design service

JIDE Docking Framework JIDE Grids JIDE Pivot Grid JIDE Data Grids JIDE Desktop Application Framework

2

Goal> Explore the internals of JTable > Find a way to enhance it to meet requirements

3

JTable: 101

4

JTableTableModel

TableUI (BasicTableUI)

JTableHeaderTableColumn

TableColumnModel

TableCellRendererTableCellEditor

JTable> Nothing but a bunch of cells arranged in grid-like

layout> Not enough in an real world application

5

Possible Enhancements: Table Header> AutoFilter (Excel style filter dropdowns)> Multiple Rows in the Header with Column Span

(nested table header)> Sortable/Groupable> Show/Hide Columns (right click context menu)> Column Auto-Fit (double click on the column divider)

6

Possible Enhancements: Table Body> Cell Spanning (merge cells)> Frozen Rows/Columns (make some rows or columns

not scrollable)> Resizable Rows/Columns (drag the grid lines to resize)> Cell Styling (row/column stripes, back/foreground

color, font, flashing)> TreeTable> HierarchicalTable (put other components inside table

under each row)

7

Possible Enhancements: Table Model> Sorting> Filtering> Grouping> Caching> Paginating> JavaBean Support> JDBC or Hibernate Support

8

Possible Enhancements: Renderer/Editor> More cell renderers and editors for various data types

Numbers Color Date/Calendar Font Insets Array

9

Possible Enhancements: Other> State persistence (column order, width, sort order,

selection)> Key navigation (i.e. only stop on editable cells)> Excel export> Non-contiguous cell selection> Formula (like Excel)> Copy and paste (copy is supported by JTable but paste

is missing)> Cell validation and row validation

10

Things to Consider> Compatible with JTable

JTable is still moving along, there is no reason to start from scratch.

Won’t break the code for every new JDK release.> Compatible with existing code which already uses

JTable Make migration easier Developer feels at home

> Cons: face some limitations

Things we can leverage> Subclassing

JTable BasicTableUI TableModel

> Overriding JTable: prepareRenderer, prepareEditor,

changeSelection, isCellSelected, rowAtPoint etc. BasicTableUI: paint

> Leveraging existing JTable APIs listeners, keyboard actions

Case Studies> Filtering and Sorting> Cell Spanning> Cell Styling

13

Case Study: Filtering and Sorting> The original TableModel should NOT be touched> Performance and memory> Scalability

14

Demo of Sortable and Filterable Feature

15

The solution is …> View/Model Conversion

Using a row index mapping to map from the row index from the actual model to the row index in the view

> Nothing new TableColumnModel is such a view/model conversion

except it is for the columns

16

TableModelWrapper (or delegate)> It wraps any TableModel to provide a mapping of row

indices from the outer model to the inner model> Only one method

TableModel getActualModel()> RowTableModelWrapper

Provides row index mapping int getActualRowAt(int visualRowIndex) int getVisualRowAt(int actualRowIndex)

SortableTableModel

3 06 10 21 35 42 58 69 77 84 9

SortableTableModel(set to a table)

Actual TableModel

.

.

.

Implementation of getValueAt methodpublic Object getValueAt(int row, int column) { if (_indexes != null && (row < 0 || row >= _indexes.length)) { return null; } else { return _model.getValueAt(getActualRowAt(row), column); } }

where getActualRowAt is _indexes[row].

19

FilterableTableModel

0 03 19 2

3456789

FilterableTableModel(set to a table)

Actual TableModel

TableModelWrapper “Pipes”Sortable

TableModel (1)Actual

TableModel (1)

1 0 0

2 3 1

0 9 2

3

4

5

6

7

8

9

FilterableTableModel (n)

JTable

Performance and Memory> The lookup speed: a direct array access for each table

model wrapper table.getValueAt(row, column) calls

tableModel.getValueAt(getActualRowAt(row), column)> Memory consumption: one (or two) int array whose

length is the same as the row count Optional index caching feature to make reverse lookup

to make getVisualRowAt method faster Lazy initialization

The index array is not created until there is sorting The reverse index array is not created until getVisualRowAt is

called22

SortableTable> SortableTableHeader to allow click-to-sort.

23

Filterable related components> Different from SortableTable, no FilterableTable> Any JTable can be filterable if you set a

FilterableTableModel on to it> Other components work with JTable and

FilterableTableModel to make it easy for user to add/remove filters AutoFilterTableHeader QuickTableFilterField (optionally use Lucene) QuickFilterPane TableCustomFilterEditor

24

If there were one thing to learn …> Remember the row index mapping idea and the table

model wrapper design.

25

Case Style: Cell Spanning

26

> Merge several cells into one big cell

Demo of CellSpanTable

27

Brainstorming> Model: store the cell spans> View: change how the grid lines are painted

28

CellSpan> _row: Span start row index> _column: Span start column

index> _rowSpan: The number of

rows that it spans> _columnSpan: The number

of columns that it spans

CellSpan(1,2,3,4)

row, column, rowSpan, columnSpan

SpanModel> Methods:

boolean isCellSpanOn() CellSpan getCellSpanAt(int row, int column)

> Any TableModel can implement this SpanModel interface

> Implementations: AbstractSpanTableModel DefaultSpanTableModel: addCellSpan, removeCellSpan

etc. methods

Exampleclass MyModel extends AbstractTableModel implements SpanModel {

……. // all other table model methods

CellSpan span; public CellSpan getCellSpanAt(int row, int column) { // define the span based on the row and column index return span; } public boolean isCellSpanOn() { return true; } }

31

Subclassing BasicTableUI> BasicCellSpanTableUI extends BasicTableUI

The paintGrid and paintCells methods are private End up overriding paint(g, c) method with many

duplicated code

Subclassing JTable> CellSpanTable

Override getCellRenderer, prepareRenderer, getCellEditor, prepareEditor, editCellAt

Override rowAtPoint, columnAtPoint and getCellRect Override isCellSelected

getCellRenderer @Override public TableCellRenderer getCellRenderer(int row, int column) { CellSpan cellSpan = getCellSpanAt(row, column); if (cellSpan != null) { return super.getCellRenderer(cellSpan.getRow(), cellSpan.getColumn()); } return super.getCellRenderer(row, column); }

34

Other Considerations> Caching CellSpans at CellSpanTable> Caching the painting of CellSpans in

BasicCellSpanTableUI to avoid the cells in the same CellSpan painted again and again

> Converting the CellSpan when columns are rearranged (not all possible)

35

If there were one thing to learn …> Store the information along the table model by

implementing a new interface

36

Case Study: Cell Styling> Background (solid color or gradient)> Foreground> Font (font name, style, size)> Border> Alignment> Icon> Row stripes/column stripes

37

Demo of CellStyleTable

38

Brainstorming> Is cell styling a model concept or a view concept?

39

Brainstorming> Is cell styling a model concept or a view concept?

It depends Row striping is certain a view concept because it has

nothing to do with the table data However “displaying red text for negative values” is

related to the table data so it is kind of a model concept

40

Brainstorming (Cont.)> Providing the Cellstyle

Using TableModel – for model related styles Using JTable – for non-model related styles

41

CellStyle> A class define styles mentioned on the previous slide

that has many setters and getters, such as Color getForeground() void setForeground(Color color) Border getBorder() void setBorder(Border border)

StyleModel> Any TableModel can implement the StyleModel

interface> Methods:

boolean isCellStyleOn() CellStyle getCellStyleAt(int row, int column)

Subclass JTable - CellStyleTable> Add setTableStyleProvider

public interface TableStyleProvider { CellStyle getCellStyleAt(JTable table, int rowIndex, int columnIndex);}

> Override prepareRenderer/prepareEditor methods

Implements Foreground Style> prepareRenderer(renderer, row, column);

Call super to get the rendererComponent Gets the CellStyle(s) from the StyleModel/TableStyleProvider If CellStyle has a foreground defined, call

rendererComponent.setForeground Repeat the previous step to cover all styles BasicTableUI will then paint the rendererComponent on the

table cell> What will happen if we only do this?

45

Implements Foreground Style> prepareRenderer(renderer, row, column);

Call super to get the rendererComponent Gets the CellStyle(s) from the StyleModel/TableStyleProvider If CellStyle has a foreground defined, call

rendererComponent.setForeground Repeat the previous step to cover all styles BasicTableUI will then paint the rendererComponent on the

table cell> What will happen if we only do this?

Because the same renderer is used in a table for different cells, all those cells will have the same foreground.

46

Implements Foreground Style: Cont.> releaseRendererComponent(renderer, row, column,

rendererComponent) We changed TableUI to always call

releaseRendererComponent after the rendererComponent is painted.

And we reset the foreground to its previous value in this method

> We suggest Sun includes this method in JTable

47

If there were one thing to learn …> Define cell styling in a consistent way for all the tables

in your application Define all CellStyle instances in one place You can even create CellStyle on fly using stylesheet or a

configuration file when application starts. getCellStyleAt return the predefined instance.

48

Showcases

49

Q & A

50

51

David QiaoJIDE Software, Inc.david@jidesoft.com

Recommended