[jsword-svn] common/java/limbo/org/crosswire/common/swing s
jswordcvs at crosswire.org
jswordcvs at crosswire.org
Sun May 8 18:28:44 MST 2005
Update of /cvs/jsword/common/java/limbo/org/crosswire/common/swing
In directory www.crosswire.org:/tmp/cvs-serv5945/java/limbo/org/crosswire/common/swing
Added Files:
MapTable.java MapCellRenderer.java RowTable.java
DebugContainerListener.java SortRenderer.java RowColumns.java
ListListModel.java RowTableModel.java
Log Message:
Moved unused code to limbo.
Upgraded support-tools: checkstyle, pmd and findbugs to most recent.
Addressed over 100 issues reported by findbugs and checkstyle.
Resulted in major refactoring of GBFFilter.
Net result is that code size is significantly smaller.
--- NEW FILE: RowTableModel.java ---
package org.crosswire.common.swing;
import java.util.List;
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
/**
* The RowTableModel defines the "model" behaviour for a RowTable.
*
* <p><table border='1' cellPadding='3' cellSpacing='0'>
* <tr><td bgColor='white' class='TableRowColor'><font size='-7'>
*
* Distribution Licence:<br />
* JSword is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License,
* version 2 as published by the Free Software Foundation.<br />
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.<br />
* The License is available on the internet
* <a href='http://www.gnu.org/copyleft/gpl.html'>here</a>, or by writing to:
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA<br />
* The copyright to this program is held by it's authors.
* </font></td></tr></table>
* @see gnu.gpl.Licence
* @author DM Smith [dmsmith555 at yahoo dot com]
* @author Joe Walker [joe at eireneh dot com]
* @version $Id: RowTableModel.java,v 1.1 2005/05/09 01:28:42 dmsmith Exp $
*/
public class RowTableModel extends AbstractTableModel
{
/**
* Builds a RowTable model for the provided (non-null) row list,
* using the provided row column definition.
* @param newList List
*/
public RowTableModel(List newList, RowColumns aRowColumnModel)
{
list = new ArrayList();
list.addAll(newList);
rowColumnModel = aRowColumnModel;
keys = rowColumnModel.getSortKeys();
sortColumn = keys[0];
allocate();
}
/**
* Method getRowCount returns the number of rows in the list.
* @return int
* @see javax.swing.table.TableModel#getRowCount()
*/
public int getRowCount()
{
return (list == null) ? 0 : list.size();
}
/**
* Method getColumnCount returns the number of columns in the table
* @return int
* @see javax.swing.table.TableModel#getColumnCount()
*/
public int getColumnCount()
{
return rowColumnModel.getCount();
}
/**
* Method getValueAt returns the contents of a cell.
* @param row int
* @param column int
* @return Object
* @see javax.swing.table.TableModel#getValueAt(int, int)
*/
public Object getValueAt(int row, int column)
{
return getCellValue(indexes[row], column);
}
/**
* Method getCellValue Translates from a row index to a row object
* and asks it for the appropriate cell value
* @param rowIndex int
* @param columnIndex int
* @return Object
*/
private Object getCellValue(int rowIndex, int columnIndex)
{
final Object obj = list.get(rowIndex);
return rowColumnModel.getValueAt(obj, columnIndex);
}
/**
* Method getColumnClass returns the class of the column
* @param columnIndex int
* @return Class
* @see javax.swing.table.TableModel#getColumnClass(int)
*/
public Class getColumnClass(int columnIndex)
{
return rowColumnModel.getClass(columnIndex);
}
/**
* Method getHeaderToolTip returns the tooltip for the header of the column
* @param columnIndex int
* @return String
*/
public String getHeaderToolTip(int columnIndex)
{
return rowColumnModel.getHeaderToolTip(columnIndex);
}
/**
* Method getColumnName returns the header name for the column
* @param columnIndex int
* @return String
* @see javax.swing.table.TableModel#getColumnName(int)
*/
public String getColumnName(int columnIndex)
{
return rowColumnModel.getName(columnIndex);
}
/**
* Method addRow adds a row to the table.
* @param obj the row to add
*/
public void addRow(Object obj)
{
list.add(obj);
allocate();
final int visibleRow = getRow(obj);
fireTableRowsInserted(visibleRow, visibleRow);
}
/**
* Method getRow retrieves a row from the table
* @param rowIndex int
* @return the row
*/
public Object getRow(int rowIndex)
{
return list.get(indexes[rowIndex]);
}
/**
* Method getRow finds the visible row index for a given row
* @param obj the row
* @return int
*/
public int getRow(Object obj)
{
for (int i = 0; i < indexes.length; i++)
{
if (getRow(i).equals(obj))
{
return i;
}
}
return -1;
}
/**
* Method removeRow removes a row from the model
* and causes the display to update itself appropriately
* @param obj the row to remove
*/
public void removeRow(Object obj)
{
final int dataIndex = list.indexOf(obj);
final int visibleIndex = getRow(obj);
list.remove(dataIndex);
fireTableRowsDeleted(visibleIndex, visibleIndex);
allocate();
}
/**
* Method updateRow causes the display to update itself appropriately.
* Methods on rows are actually used to update the row
* @param obj the row
*/
public void updateRow(Object obj)
{
final int visibleIndex = getRow(obj);
fireTableRowsUpdated(visibleIndex, visibleIndex);
}
public void reset()
{
allocate();
fireTableDataChanged();
}
public void clear()
{
list.clear();
allocate();
fireTableDataChanged();
}
// Bubble Sort!!! Replace if performance is an issue.
/**
* Method sort
* @param modelIndex int
*/
public void sort(int modelIndex)
{
if (modelIndex != -1)
{
sortColumn = modelIndex;
}
final int rowCount = getRowCount();
boolean changed = false;
for (int i = 0; i < rowCount; i++)
{
for (int j = i + 1; j < rowCount; j++)
{
if (compareKeys(indexes[i], indexes[j], sortColumn) < 0)
{
swap(i, j);
changed = true;
}
}
}
if (changed)
{
fireTableRowsUpdated(0, getRowCount());
}
}
/**
* Method swap
* @param i int
* @param j int
*/
private void swap(int i, int j)
{
final int tmp = indexes[i];
indexes[i] = indexes[j];
indexes[j] = tmp;
}
/**
* Method compareKeys
* @param i int
* @param j int
* @param column int
* @return int
*/
private int compareKeys(int i, int j, int column)
{
int cmp = compare(i, j, column);
if (keys != null)
{
for (int k = 0; cmp == 0 && k < keys.length; k++)
{
if (k != column)
{
cmp = compare(i, j, keys[k]);
}
}
}
return cmp;
}
/**
* Method compare
* @param i int
* @param j int
* @param column int
* @return int
*/
public int compare(int i, int j, int column)
{
final Object io = getCellValue(i, column);
final Object jo = getCellValue(j, column);
int cmp = 0;
if (io.getClass().equals(jo.getClass()) && io instanceof Comparable)
{
cmp = ((Comparable) jo).compareTo(io);
}
else if (io instanceof Boolean)
{
cmp = io.toString().compareTo(jo.toString());
}
else
{
cmp = jo.toString().compareTo(io.toString());
}
return (cmp < 0) ? -1 : ((cmp > 0) ? 1 : 0);
}
/**
* Method allocate
*/
private void allocate()
{
final int rowCount = getRowCount();
if (indexes == null || indexes.length != rowCount)
{
final int[] newData = new int[rowCount];
for (int i = 0; i < rowCount; i++)
{
newData[i] = i;
}
indexes = newData;
// Do the default or last sort
sort(-1);
}
}
/**
* Serialization ID
*/
private static final long serialVersionUID = 3761126033281463602L;
/**
* Field list contains the objects that can be worked upon
*/
private List list;
/**
* Field columnModel provides the definition of the structure
* of the table
*/
private RowColumns rowColumnModel;
/**
* Field indexes provides a look-aside for the sorted view of the
* table to the row list.
*/
private int[] indexes;
/**
* Field keys provides the primary or composite key of the table.
* It is a local optimization of columnModel.getSortKeys().
*/
private int[] keys;
/**
* Field sortColumn indicates the column that was last sorted upon.
* It is initialized the first value in keys, if present otherwise -1
*/
private int sortColumn;
}
--- NEW FILE: DebugContainerListener.java ---
package org.crosswire.common.swing;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.util.HashMap;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import org.crosswire.common.util.ClassUtil;
import org.crosswire.common.util.Logger;
/**
* Attempt to find parenting errors.
*
* <p><table border='1' cellPadding='3' cellSpacing='0'>
* <tr><td bgColor='white' class='TableRowColor'><font size='-7'>
*
* Distribution Licence:<br />
* JSword is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License,
* version 2 as published by the Free Software Foundation.<br />
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.<br />
* The License is available on the internet
* <a href='http://www.gnu.org/copyleft/gpl.html'>here</a>, or by writing to:
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA<br />
* The copyright to this program is held by it's authors.
* </font></td></tr></table>
* @see gnu.gpl.Licence
* @author Joe Walker [joe at eireneh dot com]
* @version $Id: DebugContainerListener.java,v 1.1 2005/05/09 01:28:42 dmsmith Exp $
*/
public class DebugContainerListener implements ContainerListener
{
/* (non-Javadoc)
* @see java.awt.event.ContainerListener#componentAdded(java.awt.event.ContainerEvent)
*/
public void componentAdded(ContainerEvent ev)
{
Component child = ev.getChild();
Container cont = ev.getContainer();
addChild(cont, child);
}
/**
*
*/
private void setAlert(Component comp, Color color)
{
comp.setBackground(color.brighter());
if (comp instanceof JComponent)
{
JComponent jcomp = (JComponent) comp;
jcomp.setBorder(BorderFactory.createLineBorder(color, 5));
}
}
/**
*
*/
private void addChild(Container parent, Component child)
{
Container statedParent = child.getParent();
if (statedParent == null)
{
log.warn("CL1: child:" + toString(child) + "(pink), claiming getParent()=null", new Exception()); //$NON-NLS-1$ //$NON-NLS-2$
setAlert(child, Color.PINK);
}
else
{
if (statedParent != parent)
{
log.warn("CL1: child:" + toString(child) + "(cyan), getParent()=" + toString(statedParent) + "(green) added under parent=" + toString(parent) + "(yellow)", new Exception()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
setAlert(child, Color.CYAN);
setAlert(statedParent, Color.GREEN);
setAlert(parent, Color.YELLOW);
}
}
Container lastKnownParent = (Container) map.get(child);
if (lastKnownParent != null)
{
if (lastKnownParent != parent)
{
log.warn("CL1: child:" + toString(child) + "(blue), altered reparent, old parent=" + toString(lastKnownParent) + "(magenta), new parent=" + toString(parent) + "(orange)", new Exception()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
setAlert(child, Color.BLUE);
setAlert(lastKnownParent, Color.MAGENTA);
setAlert(parent, Color.ORANGE);
}
}
map.put(child, parent);
if (child instanceof Container)
{
Container cont = (Container) child;
cont.addContainerListener(this);
// if we have already added ourselves to this component
// then we don't need to dig down
Component[] children = cont.getComponents();
for (int i = 0; i < children.length; i++)
{
addChild(cont, children[i]);
}
}
}
/**
*
*/
private String toString(Component parent)
{
return ClassUtil.getShortClassName(parent, "Null") + '(' + parent.hashCode() + ')'; //$NON-NLS-1$
}
/* (non-Javadoc)
* @see java.awt.event.ContainerListener#componentRemoved(java.awt.event.ContainerEvent)
*/
public void componentRemoved(ContainerEvent ev)
{
Component child = ev.getComponent();
map.remove(child);
}
private Map map = new HashMap();
/**
* The log stream
*/
private static final Logger log = Logger.getLogger(DebugContainerListener.class);
}
--- NEW FILE: MapTable.java ---
package org.crosswire.common.swing;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
/**
* A simple table that renders text, potentially multiline.
*
* <p><table border='1' cellPadding='3' cellSpacing='0'>
* <tr><td bgColor='white' class='TableRowColor'><font size='-7'>
*
* Distribution Licence:<br />
* JSword is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License,
* version 2 as published by the Free Software Foundation.<br />
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.<br />
* The License is available on the internet
* <a href='http://www.gnu.org/copyleft/gpl.html'>here</a>, or by writing to:
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA<br />
* The copyright to this program is held by it's authors.
* </font></td></tr></table>
* @see gnu.gpl.Licence
* @author DM Smith [ dmsmith555 at yahoo dot com]
* @version $Id: MapTable.java,v 1.1 2005/05/09 01:28:42 dmsmith Exp $
*/
public class MapTable extends JTable
{
/**
* Constructor for a MapTable
*/
public MapTable()
{
this(null);
}
/**
* Constructor for a MapTable
* @param mtm
*/
public MapTable(MapTableModel mtm)
{
super(mtm);
initialized = true;
setDefaultRenderer();
}
/* (non-Javadoc)
* @see javax.swing.JTable#setModel(javax.swing.table.TableModel)
*/
public void setModel(TableModel dm)
{
assert !initialized || dm instanceof MapTableModel;
super.setModel(dm);
setDefaultRenderer();
}
/* (non-Javadoc)
* @see javax.swing.JTable#setDefaultRenderer(java.lang.Class, javax.swing.table.TableCellRenderer)
*/
public void setDefaultRenderer(Class columnclass, TableCellRenderer renderer)
{
assert renderer instanceof MapCellRenderer;
super.setDefaultRenderer(columnclass, renderer);
}
/**
* Sets the default renderer for all cells to a MapCellRenderer.
* The default renderers must be created before setDefaultRenderer is
* called. This is done in JTable after setModel is called.
*/
private void setDefaultRenderer()
{
if (initialized && (getModel() instanceof MapTableModel))
{
for (int c = 0; c < getColumnCount(); c++)
{
setDefaultRenderer(getColumnClass(c), TCR);
}
adjustRowHeight();
}
}
/**
* Set the height of the row to show all of the rendered object.
* The height of a row is set to the preferred height
* of the tallest cell in that row.
*/
private void adjustRowHeight()
{
// Get the current default height for all rows
int height = getRowHeight();
int rowcount = getRowCount();
int colcount = getColumnCount();
int margin = getRowMargin();
for (int row = 0; row < rowcount; row++)
{
// Determine highest cell in the row
int highest = height;
for (int col = 0; col < colcount; col++)
{
Component comp = prepareRenderer(TCR, row, col);
highest = Math.max(highest, comp.getPreferredSize().height + 2 * margin);
}
// Now set the row height using the preferred height
if (getRowHeight(row) != highest)
{
setRowHeight(row, highest);
}
}
}
/**
* <code>TCR</code> is a shared renderer that renders potentially
* mulitline text.
*/
private static final TableCellRenderer TCR = new MapCellRenderer();
/**
* <code>initialized</code> indicates that a TableCellRenderer
* can be set in setModel.
*/
private boolean initialized;
/**
* Serialization ID
*/
private static final long serialVersionUID = 3906091143962965817L;
}
--- NEW FILE: SortRenderer.java ---
package org.crosswire.common.swing;
import java.awt.Component;
import java.awt.Font;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
/**
* A SortRenderer indicates the column that is sorted by italizing it.
*
* <p><table border='1' cellPadding='3' cellSpacing='0'>
* <tr><td bgColor='white' class='TableRowColor'><font size='-7'>
*
* Distribution Licence:<br />
* JSword is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License,
* version 2 as published by the Free Software Foundation.<br />
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.<br />
* The License is available on the internet
* <a href='http://www.gnu.org/copyleft/gpl.html'>here</a>, or by writing to:
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA<br />
* The copyright to this program is held by it's authors.
* </font></td></tr></table>
* @see gnu.gpl.Licence
* @author DM Smith [dmsmith555 at yahoo dot com]
* @author Joe Walker [joe at eireneh dot com]
* @version $Id: SortRenderer.java,v 1.1 2005/05/09 01:28:42 dmsmith Exp $
*/
public class SortRenderer extends DefaultTableCellRenderer
{
/**
* Constructor for SortRenderer
* @param stm SegmentTableModel
*/
public SortRenderer(RowTableModel stm)
{
model = stm;
pressedColumn = null;
setHorizontalAlignment(SwingConstants.CENTER);
}
/**
* Method getTableCellRendererComponent
* @param table JTable
* @param value Object
* @param isSelected boolean
* @param hasFocus boolean
* @param row int
* @param column int
* @return Component
*/
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
if (table != null)
{
setToolTipText(model.getHeaderToolTip(column));
final JTableHeader header = table.getTableHeader();
final TableColumn tableColumn = table.getColumnModel().getColumn(column);
if (header != null)
{
setForeground(header.getForeground());
setBackground(header.getBackground());
final Font headerFont = header.getFont();
if (tableColumn == pressedColumn)
{
setFont(headerFont.deriveFont(Font.ITALIC));
}
else
{
setFont(headerFont);
}
}
}
setText((value == null) ? "" : value.toString()); //$NON-NLS-1$
setBorder(UIManager.getBorder("TableHeader.cellBorder")); //$NON-NLS-1$
return this;
}
/**
* Method getPressedColumn
* @return the table column
*/
public TableColumn getPressedColumn()
{
return pressedColumn;
}
/**
* Method setPressedColumn
* @param tc the table column
*/
public void setPressedColumn(TableColumn tc)
{
pressedColumn = tc;
}
/**
* Serialization ID
*/
private static final long serialVersionUID = 3977303200573765939L;
/**
* Field pressedColumn
*/
private TableColumn pressedColumn;
/**
* Field model
*/
private RowTableModel model;
}
--- NEW FILE: RowColumns.java ---
/*
* Distribution Licence:
* JSword is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License,
* version 2 as published by the Free Software Foundation.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
* The License is available on the internet at:
* http://www.gnu.org/copyleft/gpl.html,
* or by writing to:
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307, USA
*
* The copyright to this program is held by it's authors
* Copyright: 2004
*/
package org.crosswire.common.swing;
import javax.swing.table.DefaultTableColumnModel;
/**
* Defines the prototypes needed to display a RowTable.
* Also defines some column indexed concrete methods to access
* the prototypes.
*
* @author DM Smith [ dmsmith555 at yahoo dot com]
*/
public abstract class RowColumns extends DefaultTableColumnModel
{
/**
* Method getHeaders gets the headers for all the columns
* @return String[] of table headers.
*/
public abstract String[] getHeaders();
/**
* Method getHeaderToolTips gets the tooltips
* for the headers for all the columns
* @return String[] of table header's tooltips.
*/
public abstract String[] getHeaderToolTips();
/**
* Method getCharacterWidths gets the widths of all the columns,
* expressed in Standard Width Characters.
* @return int[] of widths in standard characters
*/
public abstract int[] getCharacterWidths();
/**
* Method getFixedWidths gives whether a column is not
* resizable (true) or resizable (false)
* @return boolean[] of whether a column is fixed
*/
public abstract boolean[] getFixedWidths();
/**
* Method getClasses indicates the type of the data in a column
* @return Class[] of data types of the columns
*/
public abstract Class[] getClasses();
/**
* Method getSortKeys returns the primary (array of size 1) or
* composite key (size > 1) used for default sorting and
* for secondary sorting.
* @return int[] of the order of columns participating in sort.
*/
public abstract int[] getSortKeys();
/**
* Method getValueAt gets the contents of a cell from a row.
* @param row the row
* @param columnIndex int
* @return Object The content of a cell from a row
*/
public abstract Object getValueAt(Object row, int columnIndex);
/**
* Method getTableName provides the string for a Titled Border.
* @return String the table name
*/
public abstract String getTableName();
/**
* Method getCount is the number of columns in the table.
* @return int the number of columns in the table.
*/
public int getCount()
{
return getHeaders().length;
}
/**
* Method getClass gets the class of a given column
* @param columnIndex int
* @return Class of the given column
*/
public Class getClass(int columnIndex)
{
final Class[] classes = getClasses();
if (classes != null && columnIndex < classes.length)
{
return classes[columnIndex];
}
return null;
}
/**
* Method getName gets the header for the given column
* @param columnIndex int
* @return String the header name of the given column
*/
public String getName(int columnIndex)
{
final String[] headers = getHeaders();
if (headers != null && columnIndex < headers.length)
{
return headers[columnIndex];
}
return null;
}
/**
* Method getClass gets the class of a given column
* @param columnIndex int
* @return Class of the given column
*/
public String getHeaderToolTip(int columnIndex)
{
final String[] tooltips = getHeaderToolTips();
if (tooltips != null && columnIndex < tooltips.length)
{
return tooltips[columnIndex];
}
return null;
}
/**
* Method isFixedWidth indicates whether a column is fixed
* @param columnIndex int
* @return boolean, true if the column cannot be resized
*/
public boolean isFixedWidth(int columnIndex)
{
final boolean[] fixedWidths = getFixedWidths();
if (fixedWidths != null && columnIndex < fixedWidths.length)
{
return fixedWidths[columnIndex];
}
return false;
}
/**
* Method getCharacterWidth gets the width of the column,
* expressed in Standard Characters
* @param columnIndex int
* @return int the number of characters wide the column is to be.
*/
public int getCharacterWidth(int columnIndex)
{
final int[] characterWidths = getCharacterWidths();
if (characterWidths != null && columnIndex < characterWidths.length)
{
return characterWidths[columnIndex];
}
return 0;
}
}
--- NEW FILE: MapCellRenderer.java ---
package org.crosswire.common.swing;
import java.awt.Color;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.table.TableCellRenderer;
/**
* A MapCellRenderer that renders multiline text.
*
* <p><table border='1' cellPadding='3' cellSpacing='0'>
* <tr><td bgColor='white' class='TableRowColor'><font size='-7'>
*
* Distribution Licence:<br />
* JSword is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License,
* version 2 as published by the Free Software Foundation.<br />
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.<br />
* The License is available on the internet
* <a href='http://www.gnu.org/copyleft/gpl.html'>here</a>, or by writing to:
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA<br />
* The copyright to this program is held by it's authors.
* </font></td></tr></table>
* @see gnu.gpl.Licence
* @author DM Smith [ dmsmith555 at yahoo dot com]
* @version $Id: MapCellRenderer.java,v 1.1 2005/05/09 01:28:42 dmsmith Exp $
*/
public class MapCellRenderer extends JTextArea implements TableCellRenderer
{
// /**
// * Create a MapCellRenderer
// */
// public MapCellRenderer()
// {
// super();
// // LATER(DM): wrapping requires the recomputation of row height.
// // This would require grabbing wrapping events
// // and for the MapTable to listen for them and to adjust row height.
// // Not sure this is worth the effort.
// // setLineWrap(true);
// // setWrapStyleWord(true);
// }
/**
* Overrides <code>JComponent.setForeground</code> to assign
* the unselected-foreground color to the specified color.
*
* @param c set the foreground color to this value
*/
public void setForeground(Color c)
{
super.setForeground(c);
unselectedForeground = c;
}
/**
* Overrides <code>JComponent.setBackground</code> to assign
* the unselected-background color to the specified color.
*
* @param c set the background color to this value
*/
public void setBackground(Color c)
{
super.setBackground(c);
unselectedBackground = c;
}
/**
* Notification from the <code>UIManager</code> that the look and feel
* [L&F] has changed.
* Replaces the current UI object with the latest version from the
* <code>UIManager</code>.
*
* @see javax.swing.JComponent#updateUI()
*/
public void updateUI()
{
super.updateUI();
setForeground(null);
setBackground(null);
}
/**
* Returns the default table cell renderer.
* @param table the <code>JTable</code>
* @param value the value to assign to the cell at <code>[row, column]</code>
* @param isSelected true if cell is selected
* @param hasFocus true if cell has focus
* @param row the row of the cell to render
* @param column the column of the cell to render
* @return the default table cell renderer
*/
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
if (isSelected)
{
super.setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
}
else
{
super.setForeground((unselectedForeground != null)
? unselectedForeground
: table.getForeground());
super.setBackground((unselectedBackground != null)
? unselectedBackground
: table.getBackground());
}
setFont(table.getFont());
if (hasFocus)
{
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder")); //$NON-NLS-1$
if (table.isCellEditable(row, column))
{
super.setForeground(UIManager.getColor("Table.focusCellForeground")); //$NON-NLS-1$
super.setBackground(UIManager.getColor("Table.focusCellBackground")); //$NON-NLS-1$
}
}
else
{
setBorder(noFocusBorder);
}
setText(value == null ? "" : value.toString()); //$NON-NLS-1$
return this;
}
/**
* <code>noFocusBorder</code> is used to present the cell as with
* the DefaultTableCellRenderer
*/
private static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
/**
* We need a place to store the color the JTextArea should be returned
* to after its foreground and background colors have been set
* to the selection background color.
* <code>unselectedForeground</code> is used to present the cell as with
* the DefaultTableCellRenderer
*/
private Color unselectedForeground;
/**
* <code>unselectedBackground</code> is used to present the cell as with
* the DefaultTableCellRenderer
*/
private Color unselectedBackground;
/**
* Serialization ID
*/
private static final long serialVersionUID = 3258130254177448499L;
}
--- NEW FILE: ListListModel.java ---
package org.crosswire.common.swing;
import java.util.List;
import javax.swing.AbstractListModel;
import javax.swing.ListModel;
/**
* A simple implementation of ListModel that is backed by a List.
*
* <p><table border='1' cellPadding='3' cellSpacing='0'>
* <tr><td bgColor='white' class='TableRowColor'><font size='-7'>
*
* Distribution Licence:<br />
* JSword is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License,
* version 2 as published by the Free Software Foundation.<br />
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.<br />
* The License is available on the internet
* <a href='http://www.gnu.org/copyleft/gpl.html'>here</a>, or by writing to:
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA<br />
* The copyright to this program is held by it's authors.
* </font></td></tr></table>
* @see gnu.gpl.Licence
* @author Joe Walker [joe at eireneh dot com]
* @version $Id: ListListModel.java,v 1.1 2005/05/09 01:28:42 dmsmith Exp $
*/
public class ListListModel extends AbstractListModel implements ListModel
{
/**
* Constructor for ListListModel.
*/
public ListListModel(List list)
{
this.list = list;
}
/**
* @see javax.swing.ListModel#getSize()
*/
public int getSize()
{
return list.size();
}
/**
* @see javax.swing.ListModel#getElementAt(int)
*/
public Object getElementAt(int index)
{
return list.get(index);
}
private List list;
/**
* Serialization ID
*/
private static final long serialVersionUID = 3977863977273209144L;
}
--- NEW FILE: RowTable.java ---
package org.crosswire.common.swing;
import java.awt.Component;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* Presents a table of items to a user in a table.
*
* <p><table border='1' cellPadding='3' cellSpacing='0'>
* <tr><td bgColor='white' class='TableRowColor'><font size='-7'>
*
* Distribution Licence:<br />
* JSword is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License,
* version 2 as published by the Free Software Foundation.<br />
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.<br />
* The License is available on the internet
* <a href='http://www.gnu.org/copyleft/gpl.html'>here</a>, or by writing to:
* Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA<br />
* The copyright to this program is held by it's authors.
* </font></td></tr></table>
* @see gnu.gpl.Licence
* @author DM Smith [dmsmith555 at yahoo dot com]
* @author Joe Walker [joe at eireneh dot com]
* @version $Id: RowTable.java,v 1.1 2005/05/09 01:28:42 dmsmith Exp $
*/
public class RowTable extends JTable
{
/**
* Constructor for RowTable
* @param aList
* @param columns
*/
public RowTable(List aList, RowColumns columns)
{
super(new RowTableModel(aList, columns));
setSortRenderer();
// Don't display vertical lines in table
// getColumnModel().setColumnMargin(0);
setColumnWidths(columns.getCharacterWidths(), columns.getFixedWidths());
getTableHeader().addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
sort(getColumnModel().getColumnIndexAtX(e.getX()));
}
});
}
/**
* Save the selection so it can be restored after sorting.
* @param aTable
* @return List
*/
private List saveSelection(JTable aTable)
{
final ListSelectionModel lsm = aTable.getSelectionModel();
final RowTableModel tm = (RowTableModel) aTable.getModel();
final int first = lsm.getMinSelectionIndex();
final int last = lsm.getMaxSelectionIndex();
final List objs = new ArrayList();
if (first != -1)
{
for (int i = first; i <= last; i++)
{
if (lsm.isSelectedIndex(i))
{
objs.add(tm.getRow(i));
}
}
}
return objs;
}
/**
* load the selections
* @param aTable JTable
* @param objs List
*/
private void loadSelection(JTable aTable, List objs)
{
final ListSelectionModel lsm = aTable.getSelectionModel();
final RowTableModel tm = (RowTableModel) aTable.getModel();
// reset the selection
for (int i = 0; i < objs.size(); i++)
{
Object obj = objs.get(i);
int where = tm.getRow(obj);
if (where != -1)
{
lsm.addSelectionInterval(where, where);
}
}
scrollToVisible(aTable);
}
/**
* Method scrollToVisible
* @param aTable JTable
*/
private void scrollToVisible(JTable aTable)
{
final ListSelectionModel lsm = aTable.getSelectionModel();
final int first = lsm.getMinSelectionIndex();
final int last = lsm.getMaxSelectionIndex();
if (first != -1)
{
final Rectangle bounds = getRowBounds(aTable, first, last);
if (!isVerticallyVisible(aTable, bounds))
{
// Is SwingUtilities.invokeLater needed ???
aTable.scrollRectToVisible(bounds);
}
}
}
/**
* Method selectRow
* @param row int
*/
public void selectRow(int row)
{
final ListSelectionModel lsm = getSelectionModel();
lsm.clearSelection();
lsm.setSelectionInterval(row, row);
scrollToVisible(this);
}
/**
* Method getRowBounds
* @param table JTable
* @param first int
* @param last int
* @return Rectangle
*/
private Rectangle getRowBounds(JTable table, int first, int last)
{
Rectangle result = table.getCellRect(first, -1, true);
result = result.union(table.getCellRect(last, -1, true));
final Insets insets = table.getInsets();
result.x = insets.left;
result.width = table.getWidth() - insets.left - insets.right;
return result;
}
/**
* Method isVerticallyVisible
* @param aTable JTable
* @param r Rectangle
* @return boolean
*/
private boolean isVerticallyVisible(JTable aTable, Rectangle r)
{
final Rectangle visible = aTable.getVisibleRect();
return visible.y <= r.y && visible.y + visible.height >= r.y + r.height;
}
/**
* Method setColumnWidths
* @param widths int[]
* @param fixed boolean[]
*/
private void setColumnWidths(int[] widths, boolean[] fixed)
{
final int mWidth = getStandardCharacterWidth();
final TableColumnModel tcm = getColumnModel();
// The << 1 accounts for two margins
// The + PADDING accounts for an extra pixel on either side
// and an extra pixel for between the columns
// that the text needs to not display ...
final int margins = (tcm.getColumnMargin() << 1) + PADDING;
for (int i = 0; i < widths.length; i++)
{
TableColumn tc = tcm.getColumn(i);
int width = widths[i] * mWidth + margins;
if (fixed[i])
{
tc.setMinWidth(width);
tc.setMaxWidth(width);
}
else
{
tc.setPreferredWidth(width);
}
}
}
/**
* Method setSortRenderer
*/
private void setSortRenderer()
{
final TableCellRenderer sortRenderer = new SortRenderer((RowTableModel) getModel());
// TableCellRenderer rowRenderer = new RowRenderer();
final TableColumnModel model = getColumnModel();
final int colCount = model.getColumnCount();
for (int i = 0; i < colCount; i++)
{
TableColumn tc = model.getColumn(i);
tc.setHeaderRenderer(sortRenderer);
}
}
/**
* Size each column to something reasonable
* We do this by getting the width of the letter 'M"
* from the default Table Header Renderer
* and set the preferred width of the column
* as the width of some number of 'M's.
* @return int
*/
private int getStandardCharacterWidth()
{
// The preferredSize of the component is more than just the character
// So we remove the extra determining the delta
// between one and two chars
final JTableHeader th = getTableHeader();
final TableCellRenderer renderer = th.getDefaultRenderer();
Component comp = renderer.getTableCellRendererComponent(this, ONE_STANDARD_CHARACTER, false, false, 0, 0);
final int oneStandardCharacterWidth = comp.getPreferredSize().width;
comp = renderer.getTableCellRendererComponent(this, TWO_STANDARD_CHARACTERS, false, false, 0, 0);
final int twoStandardCharactersWidth = comp.getPreferredSize().width;
return twoStandardCharactersWidth - oneStandardCharacterWidth;
}
/**
* Method addListSelectionListener
* @param listener ListSelectionListener
*/
public void addListSelectionListener(ListSelectionListener listener)
{
getSelectionModel().addListSelectionListener(listener);
}
/**
* Method getPreferredHeight
* @param numRows int
* @return int
*/
public int getPreferredHeight(int numRows)
{
int newHeight = getRowHeight() * numRows;
// The following may be needed for Java 1.4
// newHeight += table.getIntercellSpacing().height * (numRows + 1);
newHeight += getTableHeader().getPreferredSize().height;
final Insets insets = getInsets();
newHeight += insets.top + insets.bottom;
return newHeight;
}
/**
* Method sort
* @param col int
*/
/**
* @param col
*/
public void sort(int col)
{
if (col != -1)
{
final TableColumnModel tcm = getColumnModel();
final TableColumn tc = tcm.getColumn(col);
final SortRenderer renderer = (SortRenderer) tc.getHeaderRenderer();
renderer.setPressedColumn(tc);
}
final List objs = saveSelection(this);
getSelectionModel().clearSelection();
((RowTableModel) getModel()).sort(convertColumnIndexToModel(col));
loadSelection(this, objs);
}
/**
*
*/
public void reset()
{
final RowTableModel stm = (RowTableModel) getModel();
final ListSelectionModel lsm = getSelectionModel();
getSelectionModel().clearSelection();
lsm.clearSelection();
stm.reset();
}
/**
* Serialization ID
*/
private static final long serialVersionUID = 3761407508275081783L;
/**
* Field ONE_STANDARD_CHARACTER
*/
private static final String ONE_STANDARD_CHARACTER = "M"; //$NON-NLS-1$
/**
* Field TWO_STANDARD_CHARACTERS
*/
private static final String TWO_STANDARD_CHARACTERS = "MM"; //$NON-NLS-1$
/**
* Field PADDING
*/
private static final int PADDING = 3;
}
More information about the jsword-svn
mailing list