Swing Components Java

/*
Core SWING Advanced Programming 
By Kim Topley
ISBN: 0 13 083292 8       
Publisher: Prentice Hall  
*/
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class EditableHighlightCurrencyTable {
  public static void main(String[] args) {
    try {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
    } catch (Exception evt) {}
  
    JFrame f = new JFrame("Editable Highlighted Currency Table");
    JTable tbl = new JTable(new EditableCurrencyTableModel());
    tbl.setDefaultRenderer(java.lang.Number.class,
        new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
    TableColumnModel tcm = tbl.getColumnModel();
    tcm.getColumn(0).setPreferredWidth(150);
    tcm.getColumn(0).setMinWidth(150);
    TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
    tcm.getColumn(0).setCellRenderer(renderer);
    tbl.setShowHorizontalLines(false);
    tbl.setIntercellSpacing(new Dimension(1, 0));
    // Add the stripe renderer in the leftmost four columns.
    StripedTableCellRenderer.installInColumn(tbl, 0, Color.lightGray,
        Color.white, null, null);
    StripedTableCellRenderer.installInColumn(tbl, 1, Color.lightGray,
        Color.white, null, null);
    StripedTableCellRenderer.installInColumn(tbl, 2, Color.lightGray,
        Color.white, null, null);
    StripedTableCellRenderer.installInColumn(tbl, 3, Color.lightGray,
        Color.white, null, null);
    // Add the highlight renderer to the difference column.
    // The following comparator makes it highlight
    // cells with negative numeric values.
    Comparator cmp = new Comparator() {
      public boolean shouldHighlight(JTable tbl, Object value, int row,
          int column) {
        if (value instanceof Number) {
          double columnValue = ((Number) value).doubleValue();
          return columnValue < (double) 0.0;
        }
        return false;
      }
    };
    tcm.getColumn(3).setCellRenderer(
        new HighlightRenderer(cmp, null, Color.pink, Color.black,
            Color.pink.darker(), Color.white));
    tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
    JScrollPane sp = new JScrollPane(tbl);
    f.getContentPane().add(sp, "Center");
    f.pack();
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        System.exit(0);
      }
    });
    f.setVisible(true);
  }
}
class EditableCurrencyTableModel extends CurrencyTableModel {
  public boolean isCellEditable(int row, int column) {
    return column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN;
  }
  public void setValueAt(Object value, int row, int column) {
    try {
      if (column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN) {
        Double newObjectValue; // New value as an Object
        double newValue; // double, for validity checking
        if (value instanceof Number) {
          // Convert Number to Double
          newValue = ((Number) value).doubleValue();
          newObjectValue = new Double(newValue);
        } else if (value instanceof String) {
          // Convert a String to a Double
          newObjectValue = new Double((String) value);
          newValue = newObjectValue.doubleValue();
        } else {
          // Unrecognized - ignore
          return;
        }
        if (newValue > (double) 0.0) {
          // Store new value, but reject zero or negative values
          data[row][column] = newObjectValue;
          data[row][DIFF_COLUMN] = new Double(
              ((Double) data[row][NEW_RATE_COLUMN]).doubleValue()
                  - ((Double) data[row][OLD_RATE_COLUMN])
                      .doubleValue());
          fireTableRowsUpdated(row, row);
        }
      }
    } catch (NumberFormatException e) {
      // Ignore a badly-formatted number
    }
  }
}
class CurrencyTableModel extends AbstractTableModel {
  protected String[] columnNames = { "Currency", "Yesterday", "Today",
      "Change" };
  // Constructor: calculate currency change to create the last column
  public CurrencyTableModel() {
    for (int i = 0; i < data.length; i++) {
      data[i][DIFF_COLUMN] = new Double(
          ((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
              - ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
    }
  }
  // Implementation of TableModel interface
  public int getRowCount() {
    return data.length;
  }
  public int getColumnCount() {
    return COLUMN_COUNT;
  }
  public Object getValueAt(int row, int column) {
    return data[row][column];
  }
  public Class getColumnClass(int column) {
    return (data[0][column]).getClass();
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  protected static final int OLD_RATE_COLUMN = 1;
  protected static final int NEW_RATE_COLUMN = 2;
  protected static final int DIFF_COLUMN = 3;
  protected static final int COLUMN_COUNT = 4;
  protected static final Class thisClass = CurrencyTableModel.class;
  protected Object[][] data = new Object[][] {
      {
          new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
              .getResource("belgium.gif"))),
          new Double(37.6460110), new Double(37.6508921), null },
      {
          new DataWithIcon("British Pound", new ImageIcon(thisClass
              .getResource("gb.gif"))), new Double(0.6213051),
          new Double(0.6104102), null },
      {
          new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
              .getResource("canada.gif"))),
          new Double(1.4651209), new Double(1.5011104), null },
      {
          new DataWithIcon("French Franc", new ImageIcon(thisClass
              .getResource("france.gif"))),
          new Double(6.1060001), new Double(6.0100101), null },
      {
          new DataWithIcon("Italian Lire", new ImageIcon(thisClass
              .getResource("italy.gif"))),
          new Double(1181.3668977), new Double(1182.104), null },
      {
          new DataWithIcon("German Mark", new ImageIcon(thisClass
              .getResource("germany.gif"))),
          new Double(1.8191804), new Double(1.8223421), null },
      {
          new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
              .getResource("japan.gif"))),
          new Double(141.0815412), new Double(121.0040432), null } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
  public FractionCellRenderer(int integer, int fraction, int align) {
    this.integer = integer; // maximum integer digits
    this.fraction = fraction; // exact number of fraction digits
    this.align = align; // alignment (LEFT, CENTER, RIGHT)
  }
  protected void setValue(Object value) {
    if (value != null && value instanceof Number) {
      formatter.setMaximumIntegerDigits(integer);
      formatter.setMaximumFractionDigits(fraction);
      formatter.setMinimumFractionDigits(fraction);
      setText(formatter.format(((Number) value).doubleValue()));
    } else {
      super.setValue(value);
    }
    setHorizontalAlignment(align);
  }
  protected int integer;
  protected int fraction;
  protected int align;
  protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
  protected void setValue(Object value) {
    if (value instanceof DataWithIcon) {
      if (value != null) {
        DataWithIcon d = (DataWithIcon) value;
        Object dataValue = d.getData();
        setText(dataValue == null ? "" : dataValue.toString());
        setIcon(d.getIcon());
        setHorizontalTextPosition(SwingConstants.RIGHT);
        setVerticalTextPosition(SwingConstants.CENTER);
        setHorizontalAlignment(SwingConstants.LEFT);
        setVerticalAlignment(SwingConstants.CENTER);
      } else {
        setText("");
        setIcon(null);
      }
    } else {
      super.setValue(value);
    }
  }
}
class DataWithIcon {
  public DataWithIcon(Object data, Icon icon) {
    this.data = data;
    this.icon = icon;
  }
  public Icon getIcon() {
    return icon;
  }
  public Object getData() {
    return data;
  }
  public String toString() {
    return data.toString();
  }
  protected Icon icon;
  protected Object data;
}
class StripedTableCellRenderer implements TableCellRenderer {
  public StripedTableCellRenderer(TableCellRenderer targetRenderer,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    this.targetRenderer = targetRenderer;
    this.evenBack = evenBack;
    this.evenFore = evenFore;
    this.oddBack = oddBack;
    this.oddFore = oddFore;
  }
  // Implementation of TableCellRenderer interface
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      // Get default renderer from the table
      renderer = table.getDefaultRenderer(table.getColumnClass(column));
    }
    // Let the real renderer create the component
    Component comp = renderer.getTableCellRendererComponent(table, value,
        isSelected, hasFocus, row, column);
    // Now apply the stripe effect
    if (isSelected == false && hasFocus == false) {
      if ((row & 1) == 0) {
        comp.setBackground(evenBack != null ? evenBack : table
            .getBackground());
        comp.setForeground(evenFore != null ? evenFore : table
            .getForeground());
      } else {
        comp.setBackground(oddBack != null ? oddBack : table
            .getBackground());
        comp.setForeground(oddFore != null ? oddFore : table
            .getForeground());
      }
    }
    return comp;
  }
  // Convenience method to apply this renderer to single column
  public static void installInColumn(JTable table, int columnIndex,
      Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
    TableColumn tc = table.getColumnModel().getColumn(columnIndex);
    // Get the cell renderer for this column, if any
    TableCellRenderer targetRenderer = tc.getCellRenderer();
    // Create a new StripedTableCellRenderer and install it
    tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
        evenBack, evenFore, oddBack, oddFore));
  }
  // Convenience method to apply this renderer to an entire table
  public static void installInTable(JTable table, Color evenBack,
      Color evenFore, Color oddBack, Color oddFore) {
    StripedTableCellRenderer sharedInstance = null;
    int columns = table.getColumnCount();
    for (int i = 0; i < columns; i++) {
      TableColumn tc = table.getColumnModel().getColumn(i);
      TableCellRenderer targetRenderer = tc.getCellRenderer();
      if (targetRenderer != null) {
        // This column has a specific renderer
        tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
            evenBack, evenFore, oddBack, oddFore));
      } else {
        // This column uses a class renderer - use a shared renderer
        if (sharedInstance == null) {
          sharedInstance = new StripedTableCellRenderer(null,
              evenBack, evenFore, oddBack, oddFore);
        }
        tc.setCellRenderer(sharedInstance);
      }
    }
  }
  protected TableCellRenderer targetRenderer;
  protected Color evenBack;
  protected Color evenFore;
  protected Color oddBack;
  protected Color oddFore;
}
interface Comparator {
  public abstract boolean shouldHighlight(JTable tbl, Object value, int row,
      int column);
}
class HighlightRenderer implements TableCellRenderer {
  public HighlightRenderer(Comparator cmp, TableCellRenderer targetRenderer,
      Color backColor, Color foreColor, Color highlightBack,
      Color highlightFore) {
    this.cmp = cmp;
    this.targetRenderer = targetRenderer;
    this.backColor = backColor;
    this.foreColor = foreColor;
    this.highlightBack = highlightBack;
    this.highlightFore = highlightFore;
  }
  public Component getTableCellRendererComponent(JTable tbl, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    TableCellRenderer renderer = targetRenderer;
    if (renderer == null) {
      renderer = tbl.getDefaultRenderer(tbl.getColumnClass(column));
    }
    Component comp = renderer.getTableCellRendererComponent(tbl, value,
        isSelected, hasFocus, row, column);
    if (isSelected == false && hasFocus == false && value != null) {
      if (cmp.shouldHighlight(tbl, value, row, column)) {
        comp.setForeground(highlightFore);
        comp.setBackground(highlightBack);
      } else {
        comp.setForeground(foreColor);
        comp.setBackground(backColor);
      }
    }
    return comp;
  }
  protected Comparator cmp;
  protected TableCellRenderer targetRenderer;
  protected Color backColor;
  protected Color foreColor;
  protected Color highlightBack;
  protected Color highlightFore;
}