|
From: Lieven D. (JIRA) <no...@sp...> - 2008-10-09 20:31:25
|
[ http://jira.springframework.org/browse/RCP-189?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Lieven Doclo updated RCP-189:
-----------------------------
Fix Version/s: 1.x
> TableUtils resizing columns should take into account all rows.
> --------------------------------------------------------------
>
> Key: RCP-189
> URL: http://jira.springframework.org/browse/RCP-189
> Project: Spring Framework Rich Client Project
> Issue Type: Improvement
> Components: Helper Classes
> Reporter: Benoit Xhenseval
> Assignee: Oliver Hutchison
> Fix For: 1.x
>
>
> Hi
> As discussed at the end of post http://forum.springframework.org/viewtopic.php?t=8933 , the current implementation TableUtils.sizeColumnsToFitRowData(JTable) just looks at the first row. It is understandable if the table contains thousands of rows...
> Here is an alternative solution; it takes 250ms on my old laptop (1GHz) to resize a table of 7 columsn and 2,000 rows.
> [code]
> /**
> * Resize the columns based on the data contained in all rows and Header.
> * The original width will be based on the value of the column header, and,
> * will be expanded if at least one row requires more space. The column header
> * size is slightly padded to allow for sorting icons (GlazedTableModel).
> * @param table the table to resize
> * @author Benoit Xhenseval (modified)
> */
> public static void sizeColumnsToFitAllRowData(JTable table) {
> // go through each column first to take the renderer.
> for (int col = 0; col < table.getColumnCount(); col++) {
> final TableColumnModel colModel = table.getColumnModel();
> final TableModel model = table.getModel();
> TableColumn column = colModel.getColumn(col);
> TableCellRenderer r = colModel.getColumn(col).getCellRenderer();
> // original width should be based on the size of the HEADER.
> int cWidth = table.getTableHeader().getFontMetrics(table.getTableHeader().getFont()).stringWidth(
> model.getColumnName(col) + "XXXX"); // we have added 'XXXX' to allow space for sorting icons.
> for (int row = 0; row < table.getRowCount(); row++) {
> if (r == null) {
> Object val = table.getValueAt(row, col);
> if (val != null) {
> r = table.getDefaultRenderer(val.getClass());
> }
> }
> if (r != null) {
> Component c = r.getTableCellRendererComponent(table, table.getValueAt(row, col), false, false, 0,
> col);
> cWidth = Math.max(c.getPreferredSize().width, cWidth);
> }
> }
> column.setPreferredWidth(cWidth + UIConstants.ONE_SPACE);
> column.setWidth(cWidth);
> }
> int width = Math.min(table.getColumnModel().getTotalColumnWidth(), (int) (WindowUtils.getScreenWidth() * .75));
> table.setPreferredScrollableViewportSize(new Dimension(width, 300));
> }
> [/code]
> since the name is slightly different, could you add this method to the TableUtils? Thanks!
> We have also experienced some optimizations by quickly going through the values of each row and simply doing a toString() to it, then picking up the row
> where the string is the biggest and only try to render that row. It is not the most accurate method if you have some funny
> rendering (say Date formatting that abbreviate a Date dramatically). But for big tables, it would be faster! For our example
> of 2,000 rows & 7 columns, it is about 30% faster.
> Here is the code, again, we have named the method slightly differently so they can co-exist:
> [code]
> public static void sizeColumnsToFitAllRowDataBasedOnStrings(JTable table) {
> for (int col = 0; col < table.getColumnCount(); col++) {
> final TableColumnModel colModel = table.getColumnModel();
> final TableModel model = table.getModel();
> TableColumn column = colModel.getColumn(col);
> TableCellRenderer r = colModel.getColumn(col).getCellRenderer();
> // original width should be based on the size of the HEADER.
> int cWidth = table.getTableHeader().getFontMetrics(table.getTableHeader().getFont()).stringWidth(
> model.getColumnName(col) + "XXXX"); // we have added 'XXXX' to allow space for sorting icons.
> // now simply spot the row that has the biggest "string"
> int maxStringLength = 0;
> Object maxRowValue = null;
> int maxRowIndex = 0;
> for (int row = 0; row < table.getRowCount(); row++) {
> Object value = table.getValueAt(row, col);
> if (value != null) {
> final int length = value.toString().length();
> if (length > maxStringLength) {
> maxStringLength = length;
> maxRowValue = value;
> maxRowIndex = row;
> }
> }
> }
> // and uses that row for the rendering.
> if (r == null) {
> Object val = table.getValueAt(maxRowIndex, col);
> if (val != null) {
> r = table.getDefaultRenderer(val.getClass());
> }
> }
> if (r != null) {
> Component c = r.getTableCellRendererComponent(table, maxRowValue, false, false, 0, col);
> cWidth = Math.max(c.getPreferredSize().width, cWidth);
> }
> column.setPreferredWidth(cWidth + UIConstants.ONE_SPACE);
> column.setWidth(cWidth);
> }
> int width = Math.min(table.getColumnModel().getTotalColumnWidth(), (int) (WindowUtils.getScreenWidth() * .75));
> table.setPreferredScrollableViewportSize(new Dimension(width, 300));
> }
> [/code]
> Please let me know if/when you could put this in CVS so I can remove my own class.
> Many thanks.
> Benoit
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.springframework.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
|