package net.sf.colossus.gui;
import java.util.Enumeration;
import javax.swing.JTable;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import net.sf.colossus.common.Options;
/**
* This is a JTable that remembers the size of its columns between runs of the
* program. The column sizes are stored in the provided Options object, under
* option names that begin with the provided prefix.
*
* We override the table's TableColumnModel with one that gets the desired width
* of the column from the Options when that column is being added to the table,
* and writes the new width back to the Options when columns are resided.
*
* This class doesn't actually persist the options. The caller is responsible
* for persisting the options before shutdown and reloading them before calling
* the constructor for this class.
*
* Note that the value we store not only includes the desired widths, but also
* the column order, but we aren't using the order information when creating the
* table so the columns always appear in their original order when the program
* is restarted. This could be enhanced in the future to restore column
* ordering.
*
* @author Scott Greenman
*/
public class ColumnWidthPersistingJTable extends JTable
{
public ColumnWidthPersistingJTable(String optionName, Options options,
TableModel tableModel)
{
super(tableModel, new ColumnWidthPersistingTableColumnModel(
optionName, options));
// When you provide the JTable with a TableColumnModel, it doesn't by
// default automatically create the columns. If we don't tell it to
// do that, we end up with an empty table.
setAutoCreateColumnsFromModel(true);
}
// Exposed to package for unit testing
static class ColumnWidthPersistingTableColumnModel extends
DefaultTableColumnModel
{
private static String COLUMN_SEPARATOR = ",";
private static String FIELD_SEPARATOR = ":";
private final String optionName;
private final Options options;
public ColumnWidthPersistingTableColumnModel(String optionName,
Options options)
{
super();
this.optionName = optionName;
this.options = options;
addColumnModelListener(new TableColumnModelListener()
{
public void columnAdded(TableColumnModelEvent e)
{
// just needed to satisfy the interface
}
public void columnRemoved(TableColumnModelEvent e)
{
// just needed to satisfy the interface
}
public void columnMoved(TableColumnModelEvent e)
{
// just needed to satisfy the interface
}
public void columnSelectionChanged(ListSelectionEvent e)
{
// just needed to satisfy the interface
}
/**
* This gets called for each column when the table is being
* created, and again if a column is resized. Update the option
* with the current field sizes.
*/
public void columnMarginChanged(ChangeEvent e)
{
StringBuilder optionValueBuilder = new StringBuilder(50);
Enumeration<TableColumn> columns = getColumns();
while (columns.hasMoreElements())
{
TableColumn column = columns.nextElement();
optionValueBuilder.append(column.getModelIndex())
.append(FIELD_SEPARATOR).append(column.getWidth())
.append(COLUMN_SEPARATOR);
}
getOptions().setOption(getOptionName(),
optionValueBuilder.toString());
}
});
}
/**
* We override addColumn() to set the preferred width
*/
@Override
public void addColumn(TableColumn aColumn)
{
int preferredWidth = getPreferredWidth(options, optionName,
aColumn.getModelIndex());
if (preferredWidth != -1)
{
aColumn.setPreferredWidth(preferredWidth);
}
super.addColumn(aColumn);
}
public String getOptionName()
{
return optionName;
}
public Options getOptions()
{
return options;
}
public int getPreferredWidth(Options options, String optionName,
int dataModelColumnNumber)
{
int preferredWidth = -1;
String preferredWidths = options.getStringOption(optionName);
if (preferredWidths == null)
{
return preferredWidth;
}
String colNumAsString = Integer.toString(dataModelColumnNumber);
String[] cols = preferredWidths.split(COLUMN_SEPARATOR);
for (String col : cols)
{
String[] fields = col.split(FIELD_SEPARATOR);
if (fields.length == 2)
{
String column = fields[0].trim();
String value = fields[1].trim();
if (column.length() > 0 && value.length() > 0
&& colNumAsString.equals(column))
{
preferredWidth = Integer.parseInt(value);
break;
}
}
}
return preferredWidth;
}
}
}