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
Top Related