001 package org.springframework.richclient.settings.support; 002 003 import javax.swing.JTable; 004 import javax.swing.table.TableColumn; 005 006 import org.apache.commons.logging.Log; 007 import org.apache.commons.logging.LogFactory; 008 import org.springframework.richclient.settings.Settings; 009 import org.springframework.util.Assert; 010 import org.springframework.util.StringUtils; 011 012 public class TableMemento implements Memento { 013 private static final Log logger = LogFactory.getLog(TableMemento.class); 014 015 private static final String COLUMN_WIDTHS = "columnWidths"; 016 017 private static final String COLUMN_ORDER = "columnOrder"; 018 019 private static final String SELECTED_ROWS = "selectedRows"; 020 021 private static final String ANCHOR = "anchor"; 022 023 private static final String LEAD = "lead"; 024 025 private JTable table; 026 027 private String key; 028 029 public TableMemento(JTable table, String key) { 030 Assert.notNull(table, "Table cannot be null"); 031 Assert.isTrue(StringUtils.hasText(key) || StringUtils.hasText(table.getName()), 032 "Key is empty or table has no name"); 033 034 if (!StringUtils.hasText(key)) { 035 key = table.getName(); 036 } 037 038 this.table = table; 039 this.key = key; 040 } 041 042 public TableMemento(JTable table) { 043 this(table, null); 044 } 045 046 public void saveState(Settings settings) { 047 saveSelectedRows(settings); 048 saveColumnOrder(settings); 049 saveColumnWidths(settings); 050 } 051 052 void saveColumnWidths(Settings settings) { 053 StringBuffer sb = new StringBuffer(); 054 int columnCount = table.getColumnCount(); 055 for (int i = 0; i < columnCount; i++) { 056 sb.append(table.getColumnModel().getColumn(i).getWidth()); 057 if (i < columnCount - 1) { 058 sb.append(","); 059 } 060 } 061 settings.setString(key + "." + COLUMN_WIDTHS, sb.toString()); 062 } 063 064 void saveColumnOrder(Settings settings) { 065 StringBuffer sb = new StringBuffer(); 066 for (int i = 0; i < table.getColumnModel().getColumnCount(); i++) { 067 TableColumn column = table.getColumnModel().getColumn(i); 068 sb.append(column.getModelIndex()); 069 if (i < table.getColumnModel().getColumnCount() - 1) { 070 sb.append(","); 071 } 072 } 073 settings.setString(key + "." + COLUMN_ORDER, sb.toString()); 074 } 075 076 void saveSelectedRows(Settings settings) { 077 String settingsKey = key + "." + SELECTED_ROWS; 078 if (settings.contains(settingsKey)) { 079 settings.remove(settingsKey); 080 } 081 082 if (table.getSelectedRowCount() > 0) { 083 settings.setInt(key + "." + ANCHOR, table.getSelectionModel().getAnchorSelectionIndex()); 084 settings.setInt(key + "." + LEAD, table.getSelectionModel().getLeadSelectionIndex()); 085 } 086 087 String selectionString = ArrayUtil.asIntervalString(table.getSelectedRows()); 088 if (selectionString.length() > 0) { 089 settings.setString(settingsKey, selectionString); 090 } 091 } 092 093 public void restoreState(Settings settings) { 094 restoreColumnOrder(settings); 095 restoreColumnWidths(settings); 096 restoreSelectedRows(settings); 097 } 098 099 void restoreColumnWidths(Settings settings) { 100 table.getSelectionModel().clearSelection(); 101 String widthSetting = settings.getString(key + "." + COLUMN_WIDTHS); 102 if (StringUtils.hasText(widthSetting)) { 103 104 String[] stringWidths = widthSetting.split(","); 105 106 try { 107 int[] widths = ArrayUtil.toIntArray(stringWidths); 108 109 if (widths.length == table.getColumnCount()) { 110 for (int i = 0; i < widths.length; i++) { 111 table.getColumnModel().getColumn(i).setWidth(widths[i]); 112 table.getColumnModel().getColumn(i).setPreferredWidth(widths[i]); 113 } 114 } else { 115 logger.warn("Unable to restore column widths, table has " + table.getColumnCount() + " columns, " 116 + widths.length + " columns stored in settings"); 117 } 118 } catch (IllegalArgumentException e) { 119 logger.warn("Unable to restore column widths", e); 120 } 121 } 122 } 123 124 void restoreSelectedRows(Settings settings) { 125 table.getSelectionModel().clearSelection(); 126 if (settings.contains(key + "." + SELECTED_ROWS)) { 127 String selection = settings.getString(key + "." + SELECTED_ROWS); 128 if (StringUtils.hasText(selection)) { 129 String[] parts = selection.split(","); 130 131 // find max row, so we can check before restoring row selections 132 String lastPart = parts[parts.length - 1]; 133 int maxRow = -1; 134 if (lastPart.indexOf('-') >= 0) { 135 maxRow = Integer.parseInt(lastPart.substring(lastPart.indexOf('-'))); 136 } else { 137 maxRow = Integer.parseInt(lastPart); 138 } 139 if (maxRow <= table.getRowCount() - 1) { 140 for (int i = 0; i < parts.length; i++) { 141 if (parts[i].indexOf('-') >= 0) { 142 String[] tmp = parts[i].split("-"); 143 table.addRowSelectionInterval(Integer.parseInt(tmp[0]), Integer.parseInt(tmp[1])); 144 } else { 145 int index = Integer.parseInt(parts[i]); 146 table.addRowSelectionInterval(index, index); 147 } 148 } 149 } else { 150 logger.warn("Unable to restore row selection, table has " + table.getRowCount() 151 + " rows, setting has max row " + maxRow); 152 } 153 } 154 } 155 156 if (settings.contains(key + "." + ANCHOR)) { 157 table.getSelectionModel().setAnchorSelectionIndex(settings.getInt(key + "." + ANCHOR)); 158 } 159 if (settings.contains(key + "." + LEAD)) { 160 table.getSelectionModel().setLeadSelectionIndex(settings.getInt(key + "." + LEAD)); 161 } 162 } 163 164 void restoreColumnOrder(Settings settings) { 165 table.getSelectionModel().clearSelection(); 166 String orderSetting = settings.getString(key + "." + COLUMN_ORDER); 167 if (StringUtils.hasText(orderSetting)) { 168 String[] stringColumns = orderSetting.split(","); 169 170 try { 171 int[] columns = ArrayUtil.toIntArray(stringColumns); 172 173 if (columns.length == table.getColumnCount()) { 174 for (int i = 0; i < columns.length; i++) { 175 table.moveColumn(getPosition(table, columns[i]), i); 176 } 177 } else { 178 logger.warn("Unable to restore column order, table has " + table.getColumnCount() + " columns, " 179 + columns.length + " columns stored in settings"); 180 } 181 } catch (IllegalArgumentException e) { 182 logger.warn("Unable to restore column order.", e); 183 } 184 } 185 } 186 187 /** 188 * Returns the position of the column for the given model index. The model 189 * index remains constant, but the position changes as the columns are 190 * moved. 191 * 192 * @param table 193 * the table 194 * @param modelIndex 195 * the modelIndex 196 * @return the position 197 */ 198 private static int getPosition(JTable table, int modelIndex) { 199 for (int i = 0; i < table.getColumnCount(); i++) { 200 TableColumn column = table.getColumnModel().getColumn(i); 201 if (column.getModelIndex() == modelIndex) { 202 return i; 203 } 204 } 205 throw new IllegalArgumentException("No column with modelIndex " + modelIndex + " found"); 206 } 207 208 protected String getKey() { 209 return key; 210 } 211 212 public JTable getTable() { 213 return table; 214 } 215 }