/* 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; } }