/*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version. You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.aitools.programd.interfaces.graphical;
import java.awt.Component;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
/**
* A generic panel that displays a sortable, loadable table.
*
* @author Richard Wallace
* @author <a href="mailto:noel@aitools.org">Noel Bush</a>
*/
abstract public class Tabulator extends JPanel {
private class TabulatorTableModel extends AbstractTableModel {
/**
*
*/
private static final long serialVersionUID = 1L;
/** The names of the columns in the table. */
private String[] columnNames;
/** The data of the columns in the table. */
private Object[][] data;
/**
* @param columnNamesToSet
*/
public TabulatorTableModel(String[] columnNamesToSet) {
this.columnNames = columnNamesToSet;
}
/**
* @see javax.swing.table.AbstractTableModel#getColumnClass(int)
*/
@Override
public Class<?> getColumnClass(int c) {
return this.getValueAt(0, c).getClass();
}
/**
* @see javax.swing.table.TableModel#getColumnCount()
*/
@Override
public int getColumnCount() {
return this.columnNames.length;
}
/**
* @see javax.swing.table.AbstractTableModel#getColumnName(int)
*/
@Override
public String getColumnName(int col) {
return this.columnNames[col];
}
/**
* @return the longest row
*/
public Object[] getLongestRow() {
if (this.data == null) {
return null;
}
int longestLength = 0;
int longestRow = 0;
for (int row = 0; row < this.data.length; row++) {
int rowLength = 0;
for (int column = 0; column < this.columnNames.length; column++) {
rowLength += this.data[row][column].toString().length();
}
longestLength = rowLength > longestLength ? rowLength : longestLength;
longestRow = rowLength > longestLength ? row : longestRow;
}
return this.data[longestRow];
}
/**
* @see javax.swing.table.TableModel#getRowCount()
*/
@Override
public synchronized int getRowCount() {
if (this.data == null) {
return 0;
}
return this.data.length;
}
/**
* @see javax.swing.table.TableModel#getValueAt(int, int)
*/
@Override
public Object getValueAt(int row, int col) {
return this.data[row][col];
}
/**
* Sets the table's data to the given data.
*
* @param dataToSet
*/
public synchronized void setData(Object[][] dataToSet) {
this.data = dataToSet;
this.fireTableDataChanged();
}
}
/**
*
*/
private static final long serialVersionUID = 1L;
/** The table displayed by the Tabulator. */
private JTable table;
/**
* The number of columns of data managed by the Tabulator (may be more than the number of visible columns!).
*/
private int columnCount;
/** The number of visible columns in the table. */
private int visibleColumnCount;
/** The TableModel that contains the data. */
private TabulatorTableModel dataTableModel;
/** The TableModel that sorts the data. */
private TableSorter sorterTableModel;
/**
* Creates a new <code>Tabulator</code> with the given column names.
*
* @param columnNames the column names
*/
public Tabulator(String[] columnNames) {
this.visibleColumnCount = columnNames.length;
this.dataTableModel = new TabulatorTableModel(columnNames);
this.sorterTableModel = new TableSorter(this.dataTableModel);
this.table = new JTable(this.sorterTableModel);
this.table.getTableHeader().setReorderingAllowed(false);
this.table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
this.sorterTableModel.addMouseListenerToHeaderInTable(this.table);
JScrollPane scrollPane = new JScrollPane(this.table);
this.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
this.add(scrollPane);
}
/**
* @return the number of columns in the table
*/
public int getColumnCount() {
return this.columnCount;
}
/**
* @return the sorter table model
*/
public TableSorter getSorterTableModel() {
return this.sorterTableModel;
}
/**
* @return the table
*/
public JTable getTable() {
return this.table;
}
/**
* Reloads the table with given data.
*
* @param data the data to load
*/
public void reloadData(Object[][] data) {
// Reload the data and update the column count.
this.dataTableModel.setData(data);
this.columnCount = data[0].length;
// Size the columns to fit.
TableColumn column = null;
Component component = null;
int headerWidth = 0;
int cellWidth = 0;
Object[] longestRow = this.dataTableModel.getLongestRow();
if (longestRow == null) {
return;
}
for (int index = 0; index < this.visibleColumnCount; index++) {
column = this.table.getColumnModel().getColumn(index);
component = this.table.getTableHeader().getDefaultRenderer()
.getTableCellRendererComponent(null, column.getHeaderValue(), false, false, 0, 0);
headerWidth = component.getPreferredSize().width;
component = this.table.getDefaultRenderer(this.sorterTableModel.getColumnClass(index))
.getTableCellRendererComponent(this.table, longestRow[index], false, false, 0, index);
cellWidth = component.getPreferredSize().width;
column.setPreferredWidth(Math.max(headerWidth, cellWidth));
}
}
}