/*
Wotonomy: OpenStep design patterns for pure Java applications.
Copyright (C) 2000 Blacksmith, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see http://www.gnu.org
*/
package net.wotonomy.ui.swing.components;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.text.Format;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
/**
* A cell renderer for dealing with formatted content. Subclasses can specify
* formats or colors or styles for specific values or locations in the table by
* overridding getFormatForContext(), getForegroundForContext() and/or
* getBackgroundForContext().
*
* @author michael@mpowers.net
* @version $Revision: 904 $ $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006)
* $
*/
public class FormattedCellRenderer extends DefaultTableCellRenderer {
protected Format currentFormat, defaultFormat;
protected Color defaultForeground, defaultBackground;
protected Font defaultFont;
/**
* Default constructor with no specified format.
*/
public FormattedCellRenderer() {
this((Format) null);
}
/**
* Constructor specifying a format for renderered content.
*/
public FormattedCellRenderer(Format aFormat) {
currentFormat = null;
defaultFormat = aFormat;
defaultForeground = super.getForeground();
defaultBackground = super.getForeground();
}
/**
* Returns the format currently in use to format cell content.
*
* @return The Format that is currently being used.
*/
public Format getFormat() {
return defaultFormat;
}
/**
* Sets the format to be used to format cell content.
*/
public void setFormat(Format aFormat) {
defaultFormat = aFormat;
}
/**
* Overrides to retain the default foreground color, much the same as the
* DefaultCellRenderer does. We have to do this because DefaultCellRenderer's
* ivars are private.
*/
public void setForeground(Color c) {
super.setForeground(c);
defaultForeground = c;
}
/**
* Overrides to retain the default background color, much the same as the
* DefaultCellRenderer does. We have to do this because DefaultCellRenderer's
* ivars are private.
*/
public void setBackground(Color c) {
super.setBackground(c);
defaultBackground = c;
}
/**
* Overrides to retain the default font, much the same as the
* DefaultCellRenderer does. We have to do this because DefaultCellRenderer's
* ivars are private.
*/
public void setFont(Font f) {
super.setFont(f);
defaultFont = f;
}
/**
* Overridden to format the value with the appropriate Format. If the value
* cannot be formatted with the Format, the superclass method is called.
*
* @param value An Object to be formatted.
*/
protected void setValue(Object value) {
if (currentFormat != null) {
try {
// if ( ( value instanceof Number ) && ( value.toString().indexOf( "E" ) != -1 ) )
// {
// System.out.println( "FormattedCellRenderer.setValue: format = '" + currentFormat.getClass() + "'" );
// System.out.println( "FormattedCellRenderer.setValue: value = '" + value + "'" );
// System.out.println( "FormattedCellRenderer.setValue: double value = '" + ((Number)value).doubleValue() + "'" );
// System.out.println( "FormattedCellRenderer.setValue: float value = '" + ((Number)value).floatValue() + "'" );
// System.out.println( "FormattedCellRenderer.setValue: converted = '" + currentFormat.format( value ) + "'" );
// }
// WORKAROUND: This works around what may be a rounding bug in DecimalFormat.
// (PR 256/297)
currentFormat.format(ZERO);
// DEBUG: code to test for weird one/zero problem (PR 256/297)
String result = currentFormat.format(value);
/*
* above workaround seems to be working if ( result.equals( "1" ) ) {
* System.out.println(
* "FormattedCellRenderer.setValue: Could be the ONE/ZERO problem!" );
* System.out.println( "FormattedCellRenderer.setValue: format = '" +
* currentFormat.getClass() + "'" ); System.out.println(
* "FormattedCellRenderer.setValue: original value = '" + value + "'" );
* System.out.println( "FormattedCellRenderer.setValue: result = '" + result +
* "'" ); }
*/
setText(result);
// setText( currentFormat.format( value ) );
return;
} catch (IllegalArgumentException exc) {
// fall back on superclass implementation
}
}
super.setValue(value);
}
// FIXME: remove this when possible
private static Double ZERO = new Double(0.0);
/**
* Overridden to call context delegate methods.
*/
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
Format format;
// allow for context-sensitve formatting
format = getFormatForContext(table, value, isSelected, hasFocus, row, column);
if (format != null) {
currentFormat = format;
} else {
currentFormat = defaultFormat;
}
Color color;
// allow for context-sensitve foreground color
color = getForegroundForContext(table, value, isSelected, hasFocus, row, column);
if (color != null) {
super.setForeground(color);
} else {
super.setForeground(defaultForeground);
}
// allow for context-sensitve background color
color = getBackgroundForContext(table, value, isSelected, hasFocus, row, column);
if (color != null) {
super.setBackground(color);
} else {
super.setBackground(defaultBackground);
}
// have to call this here because super defaults to table's font
Component result = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
// NOTE: DefaultTableCellRenderer returns itself.
// allow for context-sensitve font
Font font = getFontForContext(table, value, isSelected, hasFocus, row, column);
if (font != null) {
result.setFont(font);
} else {
result.setFont(defaultFont);
}
return result;
}
/**
* Override this method to provide a specific format for the specific cell to be
* rendered by this component. Any format returned by this method will take
* precedence of the format specified by setFormat().
*
* This default implementation returns null.
*
* @return A Format for this cell, or null to rely on the the format specified
* by setFormat().
*/
public Format getFormatForContext(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
return null;
}
/**
* Override this method to provide a foreground color for the renderer. Because
* the table specifies colors for selected cells, these colors will only be used
* when renderering unselected cells.
*
* This default implementation returns null.
*
* @return A Color for the foreground of the cell, or null to rely on the
* table's default color scheme.
*/
public Color getForegroundForContext(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
return null;
}
/**
* Override this method to provide a background color for the renderer. Because
* the table specifies colors for selected cells, these colors will only be used
* when renderering unselected cells.
*
* This default implementation returns null.
*
* @return A Color for the background of the cell, or null to rely on the
* table's default color scheme.
*/
public Color getBackgroundForContext(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
return null;
}
/**
* Override this method to provide a font for the renderer.
*
* This default implementation returns null.
*
* @return A Font for the cell, or null to rely on the table's default font.
*/
public Font getFontForContext(JTable table, Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
return null;
}
}