Swing JFC Java

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.EventObject;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.StringTokenizer;
import java.util.TreeSet;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.EventListenerList;
import javax.swing.plaf.basic.BasicArrowButton;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
class SortedTableModel extends AbstractTableModel {
  protected TableModel sourceModel;
  protected int[] indexValues;
  public SortedTableModel(TableModel model) {
    super();
    sourceModel = model;
  }
  public int getRowCount() {
    return sourceModel.getRowCount();
  }
  public int getColumnCount() {
    return sourceModel.getColumnCount();
  }
  public Object getValueAt(int row, int column) {
    if (indexValues != null) {
      row = getSourceIndex(row);
    }
    return sourceModel.getValueAt(row, column);
  }
  public void setValueAt(Object value, int row, int column) {
    if (indexValues != null) {
      row = getSourceIndex(row);
    }
    sourceModel.setValueAt(value, row, column);
  }
  public boolean isCellEditable(int row, int column) {
    return sourceModel.isCellEditable(row, column);
  }
  public String getColumnName(int column) {
    return sourceModel.getColumnName(column);
  }
  public Class getColumnClass(int column) {
    return sourceModel.getColumnClass(column);
  }
  public int getSourceIndex(int index) {
    if (indexValues != null) {
      return indexValues[index];
    }
    return -1;
  }
  public void sortRows(int column, boolean ascending) {
    fireTableDataChanged();
  }
  public void clearSort() {
    indexValues = null;
    fireTableDataChanged();
  }
}
class SortedColumnHeaderRenderer implements TableCellRenderer {
  protected TableCellRenderer textRenderer;
  protected SortedTableModel sortedModel;
  protected int sortColumn = -1;
  protected boolean sortAscending = true;
  public SortedColumnHeaderRenderer(SortedTableModel model,
      TableCellRenderer renderer) {
    sortedModel = model;
    textRenderer = renderer;
  }
  public SortedColumnHeaderRenderer(SortedTableModel model) {
    this(model, null);
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    Component text;
    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());
    if (textRenderer != null) {
      text = textRenderer.getTableCellRendererComponent(table, value,
          isSelected, hasFocus, row, column);
    } else {
      text = new JLabel((String) value, JLabel.CENTER);
      LookAndFeel.installColorsAndFont((JComponent) text,
          "TableHeader.background", "TableHeader.foreground",
          "TableHeader.font");
    }
    panel.add(text, BorderLayout.CENTER);
    if (column == sortColumn) {
      BasicArrowButton bab = new BasicArrowButton(
          (sortAscending ? SwingConstants.NORTH : SwingConstants.SOUTH));
      panel.add(bab, BorderLayout.WEST);
    }
    LookAndFeel.installBorder(panel, "TableHeader.cellBorder");
    return panel;
  }
  public void columnSelected(int column) {
    if (column != sortColumn) {
      sortColumn = column;
      sortAscending = true;
    } else {
      sortAscending = !sortAscending;
      if (sortAscending)
        sortColumn = -1;
    }
    if (sortColumn != -1) {
      sortedModel.sortRows(sortColumn, sortAscending);
    } else {
      sortedModel.clearSort();
    }
  }
}
class TableValues extends AbstractTableModel {
  public final static int FIRST_NAME = 0;
  public final static int LAST_NAME = 1;
  public final static int DATE_OF_BIRTH = 2;
  public final static int ACCOUNT_BALANCE = 3;
  public final static int GENDER = 4;
  public final static boolean GENDER_MALE = true;
  public final static boolean GENDER_FEMALE = false;
  public final static String[] columnNames = { "First\nName", "Last\nName",
      "Date of\nBirth", "Account\nBalance", "Gender" };
  public Object[][] values = {
      { "A", "B",
          new GregorianCalendar(1962, Calendar.FEBRUARY, 20).getTime(),
          new Float(12345.67), new Boolean(GENDER_MALE) },
      { "C", "D",
          new GregorianCalendar(1987, Calendar.JANUARY, 6).getTime(),
          new Float(23456.78), new Boolean(GENDER_MALE) },
      { "E", "F",
          new GregorianCalendar(1989, Calendar.AUGUST, 31).getTime(),
          new Float(34567.89), new Boolean(GENDER_FEMALE) },
      { "G", "H",
          new GregorianCalendar(1945, Calendar.JANUARY, 16).getTime(),
          new Float(-456.70), new Boolean(GENDER_FEMALE) },
      { "I", "J",
          new GregorianCalendar(1907, Calendar.AUGUST, 2).getTime(),
          new Float(567.00), new Boolean(GENDER_FEMALE) } };
  public int getRowCount() {
    return values.length;
  }
  public int getColumnCount() {
    return values[0].length;
  }
  public Object getValueAt(int row, int column) {
    return values[row][column];
  }
  public String getColumnName(int column) {
    return columnNames[column];
  }
  public Class getColumnClass(int column) {
    Class dataType = super.getColumnClass(column);
    if (column == ACCOUNT_BALANCE) {
      dataType = Float.class;
    } else if (column == DATE_OF_BIRTH) {
      dataType = java.util.Date.class;
    } else if ((column == FIRST_NAME) || (column == LAST_NAME)) {
      dataType = String.class;
    } else if (column == GENDER) {
      dataType = Boolean.class;
    }
    return dataType;
  }
  public boolean isCellEditable(int row, int column) {
    if (column == GENDER) {
      return true;
    }
    return false;
  }
  public void setValueAt(Object value, int row, int column) {
    values[row][column] = value;
  }
}
public class SimpleTableTestMultilineHeader extends JFrame {
  protected JTable table;
  protected SortedColumnHeaderRenderer renderer;
  public static void main(String[] args) {
    SimpleTableTestMultilineHeader stt = new SimpleTableTestMultilineHeader();
    stt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    stt.setSize(400, 200);
    stt.setVisible(true);
  }
  public SimpleTableTestMultilineHeader() {
    Container pane = getContentPane();
    pane.setLayout(new BorderLayout());
    TableValues tv = new TableValues();
    SortedTableModel stm = new SortedTableModel(tv);
    stm.sortRows(TableValues.ACCOUNT_BALANCE, true);
    table = new JTable(stm);
    table.setRowSelectionAllowed(false);
    table.setColumnSelectionAllowed(true);
    TableColumnModel tcm = table.getColumnModel();
    TableColumn tc = tcm.getColumn(TableValues.GENDER);
    MultiLineHeaderRenderer mlhr = new MultiLineHeaderRenderer();
    tc = tcm.getColumn(TableValues.ACCOUNT_BALANCE);
    tc.setHeaderRenderer(mlhr);
    renderer = new SortedColumnHeaderRenderer(stm, mlhr);
    int count = tcm.getColumnCount();
    for (int i = 0; i < count; i++) {
      tc = tcm.getColumn(i);
      tc.setHeaderRenderer(renderer);
    }
    JTableHeaderToolTips jthtt = new JTableHeaderToolTips(table
        .getColumnModel());
    jthtt.setToolTips(new String[] { "Customer's First Name",
        "Customer's Last Name", "Customer's Date of Birth",
        "Customer's Account Balance", "Customer's Gender" });
    table.setTableHeader(jthtt);
    JScrollPane jsp = new JScrollPane(table);
    pane.add(jsp, BorderLayout.CENTER);
    addHeaderListener();
  }
  public void addHeaderListener() {
    table.getTableHeader().addMouseListener(new MouseAdapter() {
      public void mousePressed(MouseEvent event) {
        JTableHeader header = (JTableHeader) (event.getSource());
        int index = header.columnAtPoint(event.getPoint());
        Class dataType = table.getModel().getColumnClass(index);
        Class[] interfaces = dataType.getInterfaces();
        for (int i = 0; i < interfaces.length; i++) {
          if (interfaces[i].equals(java.lang.Comparable.class)) {
            renderer.columnSelected(index);
            break;
          }
        }
        table.setColumnSelectionInterval(index, index);
      }
    });
  }
}
class JTableHeaderToolTips extends JTableHeader {
  protected String[] toolTips;
  public JTableHeaderToolTips(TableColumnModel tcm) {
    super(tcm);
  }
  public void setToolTips(String[] tips) {
    toolTips = tips;
  }
  public String getToolTipText(MouseEvent event) {
    String tip = super.getToolTipText(event);
    int column = columnAtPoint(event.getPoint());
    if ((toolTips != null) && (column < toolTips.length)
        && (toolTips[column] != null)) {
      tip = toolTips[column];
    }
    return tip;
  }
}
class MultiLineHeaderRenderer extends JPanel implements TableCellRenderer {
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    JLabel label;
    removeAll();
    String[] header = ((String) value).split("\n");
    setLayout(new GridLayout(header.length, 1));
    for(String s: header){
      label = new JLabel(s, JLabel.CENTER);
      LookAndFeel.installColorsAndFont(label, "TableHeader.background",
          "TableHeader.foreground", "TableHeader.font");
      add(label);
    }
    LookAndFeel.installBorder(this, "TableHeader.cellBorder");
    return this;
  }
}