TS-4706 Bringing JTable to the Extreme - Oracle · l JTable is still moving along, there is no...

Post on 30-Jul-2020

1 views 0 download

Transcript of TS-4706 Bringing JTable to the Extreme - Oracle · l JTable is still moving along, there is no...

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

Monday, 8 June 2009

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

l JIDE Docking Frameworkl JIDE Gridsl JIDE Pivot Gridl JIDE Data Gridsl JIDE Desktop Application Framework

2

Monday, 8 June 2009

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

3

Monday, 8 June 2009

JTable: 101

4

JTableTableModel

TableUI (BasicTableUI)

JTableHeaderTableColumn

TableColumnModel

TableCellRendererTableCellEditor

Monday, 8 June 2009

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

like layout> Not enough in an real world application

5

Monday, 8 June 2009

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

Monday, 8 June 2009

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

Monday, 8 June 2009

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

8

Monday, 8 June 2009

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

data typesl Numbersl Colorl Date/Calendarl Fontl Insetsl Array

9

Monday, 8 June 2009

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

Monday, 8 June 2009

Things to Consider> Compatible with JTable

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

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

uses JTablel Make migration easierl Developer feels at home

> Cons: face some limitations

Monday, 8 June 2009

Things we can leverage> Subclassing

l JTablel BasicTableUIl TableModel

> Overridingl JTable: prepareRenderer, prepareEditor,

changeSelection, isCellSelected, rowAtPoint etc.l BasicTableUI: paint

> Leveraging existing JTable APIsl listeners, keyboard actions

Monday, 8 June 2009

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

13

Monday, 8 June 2009

Case Study: Filtering and Sorting> The original TableModel should NOT be

touched> Performance and memory> Scalability

14

Monday, 8 June 2009

Demo of Sortable and Filterable Feature

15

Monday, 8 June 2009

The solution is …> View/Model Conversion

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

> Nothing newl TableColumnModel is such a view/model

conversion except it is for the columns

16

Monday, 8 June 2009

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

mapping of row indices from the outer model to the inner model

> Only one methodl TableModel getActualModel()

> RowTableModelWrapper l Provides row index mappingl int getActualRowAt(int visualRowIndex)l int getVisualRowAt(int actualRowIndex)

Monday, 8 June 2009

SortableTableModel3 06 10 21 35 42 58 69 77 84 9

SortableTableModel(set to a table)

Actual TableModel

.

.

.

Monday, 8 June 2009

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

Monday, 8 June 2009

FilterableTableModel0 03 19 2

3456789

FilterableTableModel(set to a table)

Actual TableModel

Monday, 8 June 2009

TableModelWrapper “Pipes”Sortable

TableModel (1)Actual

TableModel (1)

1 0 02 3 10 9 2

3456789

FilterableTableModel (n)

JTable

Monday, 8 June 2009

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

each table model wrapperl 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 l Optional index caching feature to make reverse

lookup to make getVisualRowAt method fasterl Lazy initialization

l The index array is not created until there is sortingl The reverse index array is not created until

getVisualRowAt is called 22

Monday, 8 June 2009

SortableTable> SortableTableHeader to allow click-to-sort.

23

Monday, 8 June 2009

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 filtersl AutoFilterTableHeaderl QuickTableFilterField (optionally use Lucene)l QuickFilterPanel TableCustomFilterEditor

24

Monday, 8 June 2009

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

the table model wrapper design.

25

Monday, 8 June 2009

Case Style: Cell Spanning

26

> Merge several cells into one big cell

Monday, 8 June 2009

Demo of CellSpanTable

27

Monday, 8 June 2009

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

28

Monday, 8 June 2009

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

CellSpan(1,2,3,4)

row, column, rowSpan, columnSpan

CellSpan(1,2,3,4)

row, column, rowSpan, columnSpan

CellSpan(1,2,3,4)

row, column, rowSpan, columnSpan

CellSpan(1,2,3,4)

row, column, rowSpan, columnSpan

CellSpan(1,2,3,4)

row, column, rowSpan, columnSpan

CellSpan(1,2,3,4)

row, column, rowSpan, columnSpan

CellSpan(1,2,3,4)

row, column, rowSpan, columnSpan

CellSpan(1,2,3,4)

row, column, rowSpan, columnSpan

CellSpan(1,2,3,4)

row, column, rowSpan, columnSpan

CellSpan(1,2,3,4)

row, column, rowSpan, columnSpan

CellSpan(1,2,3,4)

row, column, rowSpan, columnSpan

Monday, 8 June 2009

SpanModel> Methods:

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

> Any TableModel can implement this SpanModel interface

> Implementations:l AbstractSpanTableModell DefaultSpanTableModel: addCellSpan,

removeCellSpan etc. methods

Monday, 8 June 2009

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

Monday, 8 June 2009

Subclassing BasicTableUI> BasicCellSpanTableUI extends BasicTableUI

l The paintGrid and paintCells methods are private

l End up overriding paint(g, c) method with many duplicated code

Monday, 8 June 2009

Subclassing JTable> CellSpanTable

l Override getCellRenderer, prepareRenderer, getCellEditor, prepareEditor, editCellAt

l Override rowAtPoint, columnAtPoint and getCellRect

l Override isCellSelected

Monday, 8 June 2009

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

Monday, 8 June 2009

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

Monday, 8 June 2009

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

by implementing a new interface

36

Monday, 8 June 2009

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

37

Monday, 8 June 2009

Demo of CellStyleTable

38

Monday, 8 June 2009

Brainstorming> Is cell styling a model concept or a view

concept?

39

Monday, 8 June 2009

Brainstorming> Is cell styling a model concept or a view

concept?l It dependsl Row striping is certain a view concept because

it has nothing to do with the table datal However “displaying red text for negative

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

40

Monday, 8 June 2009

Brainstorming (Cont.)> Providing the Cellstyle

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

41

Monday, 8 June 2009

CellStyle> A class define styles mentioned on the

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

Monday, 8 June 2009

StyleModel> Any TableModel can implement the

StyleModel interface> Methods:

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

Monday, 8 June 2009

Subclass JTable - CellStyleTable> Add setTableStyleProvider

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

> Override prepareRenderer/prepareEditor methods

Monday, 8 June 2009

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

l Call super to get the rendererComponentl Gets the CellStyle(s) from the StyleModel/

TableStyleProviderl If CellStyle has a foreground defined, call

rendererComponent.setForegroundl Repeat the previous step to cover all stylesl BasicTableUI will then paint the rendererComponent

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

45

Monday, 8 June 2009

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

l Call super to get the rendererComponentl Gets the CellStyle(s) from the StyleModel/

TableStyleProviderl If CellStyle has a foreground defined, call

rendererComponent.setForegroundl Repeat the previous step to cover all stylesl BasicTableUI will then paint the rendererComponent

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

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

46

Monday, 8 June 2009

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

column, rendererComponent)l We changed TableUI to always call

releaseRendererComponent after the rendererComponent is painted.

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

> We suggest Sun includes this method in JTable

47

Monday, 8 June 2009

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

the tables in your applicationl Define all CellStyle instances in one placel You can even create CellStyle on fly using

stylesheet or a configuration file when application starts.

l getCellStyleAt return the predefined instance.

48

Monday, 8 June 2009

Showcases

49

Monday, 8 June 2009

Q & A

50

Monday, 8 June 2009

51

David QiaoJIDE Software, Inc.david@jidesoft.com

Monday, 8 June 2009