/* * TableToGridMapper.java 0.90 00/03/26 * * Copyright 2000 Eliad Technologies, Inc. All Rights Reserved. * * This software is the proprietary information of Eliad Technologies, Inc. */ package example04; import javax.swing.table.*; import javax.swing.event.*; import com.eliad.model.*; /** * A wrapper class to present a table model, with an optional companion * table column model, as a grid model. This makes it easy to use a JSmartGrid * to display the same data as a JTable. The class directly implements the * GridModel that the JSmartGrid view will need, and also provides, through * the getColumnHeaderModel method, the GridModel needed for a column * header similar to the traditional JTableHeader. * The easiest way to display a TableModel in a grid is the following: *
import com.eliad.swing.*; * ... * TableModel tm; * ... * TableToGridMapper mapper=new TableToGridMapper(tm); * JSmartGrid grid=new JSmartGrid(mapper); * grid.setAutoCreateRowHeader(true); * grid.setAutoCreateColumnHeader(true);* If you put the grid in a JScrollPane, in the usual way: *
JScrollPane scrollPane = new JScrollPane(grid); * ... * panel.add(scrollPane); * ... * frame.add(panel); * ... * frame.pack();* two headers will appear, a row header with line numbers, and a column * header with spreadsheet-like headings. In order to have the column names * back in place, you just add (after
frame.pack()
):
*scrollPane.setColumnHeaderView( * new JSmartGridHeader(grid,grid.HORIZONTAL,mapper.getColumnHeaderModel(),null,null);*
* If you have developped a specific renderer for table cells, it should be easy to transform into
* a specific renderer for grid cells. The base interface is GridCellRenderer
. If you extended
* from the DefaultTableCellRenderer
, it is especially simple. You just change:
*
class MyRenderer extends DefaultTableCellRenderer {* into *
class MyRenderer extends DefaultGridCellRenderer {* More often that not, that will be enough, unless you overloaded the
getTableCellRenderComponent
method,
* which you often leave alone when you are subclassing the default renderers. If you did, and of course if you
* subclassed directly TableCellRenderer
(which becomes GridCellRenderer
), then you must
* note the following differences:getComponent
JTable
one is:
*JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column* while ours is: *
Object value,boolean hasFocus, boolean isSelected, boolean isEditable, * int row, int column, GridContext gridContext* Parameters with the same name of course have the same meaning. We have added the
isEditable
* flag parameter, which the TableCellRenderer
queries from the JTable
, to harmonize
* its handling with the two other flags, and the JTable
parameter has been replaced by a
* GridContext
parameter. This way the GridCellRenderer
is not tied to the
* JSmartGrid
, but could be reused with other grid-like components.
*/
public class TableToGridMapper extends AbstractGridModel
implements TableModelListener, TableColumnModelListener {
private TableModel source_;
private TableColumnModel columns_;
private GridModel columnHeaderModel_;
/**
* Default constructor for use as a bean by IDEs.
*/
public TableToGridMapper() {
}
/**
* Constructs a grid model from a table model.
*/
public TableToGridMapper(TableModel source) {
this(source, null);
}
/**
* Constructs a grid model from a table model and a table column model.
*/
public TableToGridMapper(TableModel source, TableColumnModel columns) {
setTableModel(source);
if (columns!=null)
setTableColumnModel(columns);
}
/**
* @return The original table model on which this grid model is built.
*/
public TableModel getTableModel() {
return source_;
}
/**
* Attaches a table model to this TableToGridMapper object.
*/
public void setTableModel(TableModel source) {
if (source!=source_) {
if (source_!=null)
source_.removeTableModelListener(this);
setTableColumnModel(null);
source_=source;
if (source_==null)
columnHeaderModel_=null;
else {
source_.addTableModelListener(this);
columnHeaderModel_=new AbstractGridModel() {
public int getRowCount() {
return 1;
}
public int getColumnCount() {
return source_.getColumnCount();
}
public Object getValueAt(int row, int column) {
return source_.getColumnName(column);
}
};
}
fireGridModelChanged();
}
}
/**
* Returns the table column model that was passed to this grid model
* at construction time. May be null.
*/
public TableColumnModel getTableColumnModel() {
return columns_;
}
public void setTableColumnModel(TableColumnModel columns) {
if (columns!=columns_) {
if (columns_!=null)
columns_.removeColumnModelListener(this);
columns_=columns;
if (columns_!=null) {
columns_.addColumnModelListener(this);
columnHeaderModel_=new AbstractGridModel() {
public int getRowCount() {
return 1;
}
public int getColumnCount() {
return columns_.getColumnCount();
}
public Object getValueAt(int row, int column) {
return columns_.getColumn(column).getHeaderValue();
}
};
fireGridModelChanged();
}
}
}
/**
* returns a grid model suitable for the rows header of the grid
*/
public GridModel getColumnHeaderModel() {
return columnHeaderModel_;
}
/**
* Returns the row count of this grid model
*
* @return The row count of the model, which is identical to the one of the table model.
*/
public int getRowCount() {
return source_==null?0:source_.getRowCount();
}
/**
* Returns the column count of this grid model
*
* @return The column count of the model, which is identical to the one of the table model.
*/
public int getColumnCount() {
return source_==null?0:source_.getColumnCount();
}
/**
* Returns true if the cell at row and column is editable.
* Otherwise, setValueAt on the cell will not change the value of that cell.
*
* @param row The row of the cell whose editability is to be queried.
* @param column The column of the cell whose editability is to be queried.
* @return The corresponding flag for the table model
*/
public boolean isCellEditable(int row, int column) {
return source_!=null && source_.isCellEditable(row, column);
}
/**
* Returns the value the cell at row and column.
*
* @param row The row of the cell whose value is to be queried.
* @param column The column of the cell whose value is to be queried.
* @return The value of the specified cell.
*/
public Object getValueAt(int row, int column) {
return source_==null?null:source_.getValueAt(row,column);
}
/**
* Changes the value the cell at row and column.
*
* @return The new value for the specified cell
* @param row The row of the cell whose value is to be changed.
* @param column The column of the cell whose value is to be changed.
*/
public void setValueAt(Object value,int row, int column) {
if (source_!=null)
source_.setValueAt(value,row,column);
}
/**
* Translates table model events into grid related ones
*/
public void tableChanged(TableModelEvent e) {
if (e==null) {
fireGridModelChanged();
return;
}
int sourceColumn=e.getColumn();
int firstSourceRow=e.getFirstRow();
int lastSourceRow=e.getLastRow();
boolean whole=firstSourceRow==TableModelEvent.HEADER_ROW;
boolean byRow=sourceColumn==TableModelEvent.ALL_COLUMNS;
if (whole)
fireGridModelChanged();
else {
/*
* Just computing lastSourceRow-firstSourceRow+1
* will give 0 is rowCount is Integer.MAX_VALUE,
* which is generated in some cases.
*/
int rowCount=lastSourceRow-firstSourceRow;
if (rowCount!=Integer.MAX_VALUE)
rowCount++;
switch(e.getType()) {
case TableModelEvent.UPDATE:
if (byRow)
fireGridRowsChanged(firstSourceRow,rowCount);
else
fireGridCellsChanged(firstSourceRow,sourceColumn,rowCount,1);
break;
case TableModelEvent.INSERT:
fireGridRowsInserted(firstSourceRow,rowCount);
break;
case TableModelEvent.DELETE:
fireGridRowsDeleted(firstSourceRow,rowCount);
break;
}
}
}
/**
* Translates table column model events (inserts) into grid related ones
*/
public void columnAdded(TableColumnModelEvent e) {
fireGridColumnsInserted(e.getToIndex(),1);
}
/**
* Translates table column model events (removals) into grid related ones
*/
public void columnRemoved(TableColumnModelEvent e) {
fireGridColumnsDeleted(e.getFromIndex(),1);
}
/**
* Translates table column model events (moves) into grid related ones
*/
public void columnMoved(TableColumnModelEvent e) {
fireGridModelChanged();
}
/*
* Not of concern here, but must be implemented
* since it is part of the TableColumnModelListener.
*/
public void columnMarginChanged(ChangeEvent e) {
}
/*
* Not of concern here, but must be implemented
* since it is part of the TableColumnModelListener.
*/
public void columnSelectionChanged(ListSelectionEvent e) {
}
}