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 }