Swing Components Java

// Example from http://www.crionics.com/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.Hashtable;
import java.util.Locale;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
/**
 * @version 1.0 02/25/99
 */
public class SortableTableExample extends JPanel {
  public SortableTableExample() {
    setLayout(new BorderLayout());
    String[] headerStr = { "Name", "Date", "Size", "Dir" };
    int[] columnWidth = { 100, 150, 100, 50 };
    SortableTableModel dm = new SortableTableModel() {
      public Class getColumnClass(int col) {
        switch (col) {
        case 0:
          return String.class;
        case 1:
          return Date.class;
        case 2:
          return Integer.class;
        case 3:
          return Boolean.class;
        default:
          return Object.class;
        }
      }
      public boolean isCellEditable(int row, int col) {
        switch (col) {
        case 1:
          return false;
        default:
          return true;
        }
      }
      public void setValueAt(Object obj, int row, int col) {
        switch (col) {
        case 2:
          super.setValueAt(new Integer(obj.toString()), row, col);
          return;
        default:
          super.setValueAt(obj, row, col);
          return;
        }
      }
    };
    dm
        .setDataVector(
            new Object[][] {
                { "b", getDate("98/12/02"), new Integer(14),
                    new Boolean(false) },
                { "a", getDate("99/01/01"), new Integer(67),
                    new Boolean(false) },
                { "d", getDate("99/02/11"), new Integer(2),
                    new Boolean(false) },
                { "c", getDate("99/02/27"), new Integer(7),
                    new Boolean(false) },
                { "foo", new Date(), new Integer(5),
                    new Boolean(true) },
                { "bar", new Date(), new Integer(10),
                    new Boolean(true) } }, headerStr);
    JTable table = new JTable(dm);
    //table.setShowGrid(false);
    table.setShowVerticalLines(true);
    table.setShowHorizontalLines(false);
    SortButtonRenderer renderer = new SortButtonRenderer();
    TableColumnModel model = table.getColumnModel();
    int n = headerStr.length;
    for (int i = 0; i < n; i++) {
      model.getColumn(i).setHeaderRenderer(renderer);
      model.getColumn(i).setPreferredWidth(columnWidth[i]);
    }
    JTableHeader header = table.getTableHeader();
    header.addMouseListener(new HeaderListener(header, renderer));
    JScrollPane pane = new JScrollPane(table);
    add(pane, BorderLayout.CENTER);
  }
  public static void main(String[] args) {
    JFrame f = new JFrame("SortableTable Example");
    f.getContentPane().add(new SortableTableExample(), BorderLayout.CENTER);
    f.setSize(400, 160);
    f.setVisible(true);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
  }
  private static DateFormat dateFormat = DateFormat.getDateInstance(
      DateFormat.SHORT, Locale.JAPAN);
  private static Date getDate(String dateString) {
    Date date = null;
    try {
      date = dateFormat.parse(dateString);
    } catch (ParseException ex) {
      date = new Date();
    }
    return date;
  }
  class HeaderListener extends MouseAdapter {
    JTableHeader header;
    SortButtonRenderer renderer;
    HeaderListener(JTableHeader header, SortButtonRenderer renderer) {
      this.header = header;
      this.renderer = renderer;
    }
    public void mousePressed(MouseEvent e) {
      int col = header.columnAtPoint(e.getPoint());
      int sortCol = header.getTable().convertColumnIndexToModel(col);
      renderer.setPressedColumn(col);
      renderer.setSelectedColumn(col);
      header.repaint();
      if (header.getTable().isEditing()) {
        header.getTable().getCellEditor().stopCellEditing();
      }
      boolean isAscent;
      if (SortButtonRenderer.DOWN == renderer.getState(col)) {
        isAscent = true;
      } else {
        isAscent = false;
      }
      ((SortableTableModel) header.getTable().getModel()).sortByColumn(
          sortCol, isAscent);
    }
    public void mouseReleased(MouseEvent e) {
      int col = header.columnAtPoint(e.getPoint());
      renderer.setPressedColumn(-1); // clear
      header.repaint();
    }
  }
}
class SortableTableModel extends DefaultTableModel {
  int[] indexes;
  TableSorter sorter;
  public SortableTableModel() {
  }
  public Object getValueAt(int row, int col) {
    int rowIndex = row;
    if (indexes != null) {
      rowIndex = indexes[row];
    }
    return super.getValueAt(rowIndex, col);
  }
  public void setValueAt(Object value, int row, int col) {
    int rowIndex = row;
    if (indexes != null) {
      rowIndex = indexes[row];
    }
    super.setValueAt(value, rowIndex, col);
  }
  public void sortByColumn(int column, boolean isAscent) {
    if (sorter == null) {
      sorter = new TableSorter(this);
    }
    sorter.sort(column, isAscent);
    fireTableDataChanged();
  }
  public int[] getIndexes() {
    int n = getRowCount();
    if (indexes != null) {
      if (indexes.length == n) {
        return indexes;
      }
    }
    indexes = new int[n];
    for (int i = 0; i < n; i++) {
      indexes[i] = i;
    }
    return indexes;
  }
}
class TableSorter {
  SortableTableModel model;
  public TableSorter(SortableTableModel model) {
    this.model = model;
  }
  //n2 selection
  public void sort(int column, boolean isAscent) {
    int n = model.getRowCount();
    int[] indexes = model.getIndexes();
    for (int i = 0; i < n - 1; i++) {
      int k = i;
      for (int j = i + 1; j < n; j++) {
        if (isAscent) {
          if (compare(column, j, k) < 0) {
            k = j;
          }
        } else {
          if (compare(column, j, k) > 0) {
            k = j;
          }
        }
      }
      int tmp = indexes[i];
      indexes[i] = indexes[k];
      indexes[k] = tmp;
    }
  }
  // comparaters
  public int compare(int column, int row1, int row2) {
    Object o1 = model.getValueAt(row1, column);
    Object o2 = model.getValueAt(row2, column);
    if (o1 == null && o2 == null) {
      return 0;
    } else if (o1 == null) {
      return -1;
    } else if (o2 == null) {
      return 1;
    } else {
      Class type = model.getColumnClass(column);
      if (type.getSuperclass() == Number.class) {
        return compare((Number) o1, (Number) o2);
      } else if (type == String.class) {
        return ((String) o1).compareTo((String) o2);
      } else if (type == Date.class) {
        return compare((Date) o1, (Date) o2);
      } else if (type == Boolean.class) {
        return compare((Boolean) o1, (Boolean) o2);
      } else {
        return ((String) o1).compareTo((String) o2);
      }
    }
  }
  public int compare(Number o1, Number o2) {
    double n1 = o1.doubleValue();
    double n2 = o2.doubleValue();
    if (n1 < n2) {
      return -1;
    } else if (n1 > n2) {
      return 1;
    } else {
      return 0;
    }
  }
  public int compare(Date o1, Date o2) {
    long n1 = o1.getTime();
    long n2 = o2.getTime();
    if (n1 < n2) {
      return -1;
    } else if (n1 > n2) {
      return 1;
    } else {
      return 0;
    }
  }
  public int compare(Boolean o1, Boolean o2) {
    boolean b1 = o1.booleanValue();
    boolean b2 = o2.booleanValue();
    if (b1 == b2) {
      return 0;
    } else if (b1) {
      return 1;
    } else {
      return -1;
    }
  }
}
class SortButtonRenderer extends JButton implements TableCellRenderer {
  public static final int NONE = 0;
  public static final int DOWN = 1;
  public static final int UP = 2;
  int pushedColumn;
  Hashtable state;
  JButton downButton, upButton;
  public SortButtonRenderer() {
    pushedColumn = -1;
    state = new Hashtable();
    setMargin(new Insets(0, 0, 0, 0));
    setHorizontalTextPosition(LEFT);
    setIcon(new BlankIcon());
    // perplexed
    // ArrowIcon(SwingConstants.SOUTH, true)
    // BevelArrowIcon (int direction, boolean isRaisedView, boolean
    // isPressedView)
    downButton = new JButton();
    downButton.setMargin(new Insets(0, 0, 0, 0));
    downButton.setHorizontalTextPosition(LEFT);
    downButton
        .setIcon(new BevelArrowIcon(BevelArrowIcon.DOWN, false, false));
    downButton.setPressedIcon(new BevelArrowIcon(BevelArrowIcon.DOWN,
        false, true));
    upButton = new JButton();
    upButton.setMargin(new Insets(0, 0, 0, 0));
    upButton.setHorizontalTextPosition(LEFT);
    upButton.setIcon(new BevelArrowIcon(BevelArrowIcon.UP, false, false));
    upButton.setPressedIcon(new BevelArrowIcon(BevelArrowIcon.UP, false,
        true));
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
    JButton button = this;
    Object obj = state.get(new Integer(column));
    if (obj != null) {
      if (((Integer) obj).intValue() == DOWN) {
        button = downButton;
      } else {
        button = upButton;
      }
    }
    button.setText((value == null) ? "" : value.toString());
    boolean isPressed = (column == pushedColumn);
    button.getModel().setPressed(isPressed);
    button.getModel().setArmed(isPressed);
    return button;
  }
  public void setPressedColumn(int col) {
    pushedColumn = col;
  }
  public void setSelectedColumn(int col) {
    if (col < 0)
      return;
    Integer value = null;
    Object obj = state.get(new Integer(col));
    if (obj == null) {
      value = new Integer(DOWN);
    } else {
      if (((Integer) obj).intValue() == DOWN) {
        value = new Integer(UP);
      } else {
        value = new Integer(DOWN);
      }
    }
    state.clear();
    state.put(new Integer(col), value);
  }
  public int getState(int col) {
    int retValue;
    Object obj = state.get(new Integer(col));
    if (obj == null) {
      retValue = NONE;
    } else {
      if (((Integer) obj).intValue() == DOWN) {
        retValue = DOWN;
      } else {
        retValue = UP;
      }
    }
    return retValue;
  }
}
class BevelArrowIcon implements Icon {
  public static final int UP = 0; // direction
  public static final int DOWN = 1;
  private static final int DEFAULT_SIZE = 11;
  private Color edge1;
  private Color edge2;
  private Color fill;
  private int size;
  private int direction;
  public BevelArrowIcon(int direction, boolean isRaisedView,
      boolean isPressedView) {
    if (isRaisedView) {
      if (isPressedView) {
        init(UIManager.getColor("controlLtHighlight"), UIManager
            .getColor("controlDkShadow"), UIManager
            .getColor("controlShadow"), DEFAULT_SIZE, direction);
      } else {
        init(UIManager.getColor("controlHighlight"), UIManager
            .getColor("controlShadow"), UIManager
            .getColor("control"), DEFAULT_SIZE, direction);
      }
    } else {
      if (isPressedView) {
        init(UIManager.getColor("controlDkShadow"), UIManager
            .getColor("controlLtHighlight"), UIManager
            .getColor("controlShadow"), DEFAULT_SIZE, direction);
      } else {
        init(UIManager.getColor("controlShadow"), UIManager
            .getColor("controlHighlight"), UIManager
            .getColor("control"), DEFAULT_SIZE, direction);
      }
    }
  }
  public BevelArrowIcon(Color edge1, Color edge2, Color fill, int size,
      int direction) {
    init(edge1, edge2, fill, size, direction);
  }
  public void paintIcon(Component c, Graphics g, int x, int y) {
    switch (direction) {
    case DOWN:
      drawDownArrow(g, x, y);
      break;
    case UP:
      drawUpArrow(g, x, y);
      break;
    }
  }
  public int getIconWidth() {
    return size;
  }
  public int getIconHeight() {
    return size;
  }
  private void init(Color edge1, Color edge2, Color fill, int size,
      int direction) {
    this.edge1 = edge1;
    this.edge2 = edge2;
    this.fill = fill;
    this.size = size;
    this.direction = direction;
  }
  private void drawDownArrow(Graphics g, int xo, int yo) {
    g.setColor(edge1);
    g.drawLine(xo, yo, xo + size - 1, yo);
    g.drawLine(xo, yo + 1, xo + size - 3, yo + 1);
    g.setColor(edge2);
    g.drawLine(xo + size - 2, yo + 1, xo + size - 1, yo + 1);
    int x = xo + 1;
    int y = yo + 2;
    int dx = size - 6;
    while (y + 1 < yo + size) {
      g.setColor(edge1);
      g.drawLine(x, y, x + 1, y);
      g.drawLine(x, y + 1, x + 1, y + 1);
      if (0 < dx) {
        g.setColor(fill);
        g.drawLine(x + 2, y, x + 1 + dx, y);
        g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
      }
      g.setColor(edge2);
      g.drawLine(x + dx + 2, y, x + dx + 3, y);
      g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
      x += 1;
      y += 2;
      dx -= 2;
    }
    g.setColor(edge1);
    g.drawLine(xo + (size / 2), yo + size - 1, xo + (size / 2), yo + size
        - 1);
  }
  private void drawUpArrow(Graphics g, int xo, int yo) {
    g.setColor(edge1);
    int x = xo + (size / 2);
    g.drawLine(x, yo, x, yo);
    x--;
    int y = yo + 1;
    int dx = 0;
    while (y + 3 < yo + size) {
      g.setColor(edge1);
      g.drawLine(x, y, x + 1, y);
      g.drawLine(x, y + 1, x + 1, y + 1);
      if (0 < dx) {
        g.setColor(fill);
        g.drawLine(x + 2, y, x + 1 + dx, y);
        g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
      }
      g.setColor(edge2);
      g.drawLine(x + dx + 2, y, x + dx + 3, y);
      g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
      x -= 1;
      y += 2;
      dx += 2;
    }
    g.setColor(edge1);
    g.drawLine(xo, yo + size - 3, xo + 1, yo + size - 3);
    g.setColor(edge2);
    g.drawLine(xo + 2, yo + size - 2, xo + size - 1, yo + size - 2);
    g.drawLine(xo, yo + size - 1, xo + size, yo + size - 1);
  }
}
class BlankIcon implements Icon {
  private Color fillColor;
  private int size;
  public BlankIcon() {
    this(null, 11);
  }
  public BlankIcon(Color color, int size) {
    //UIManager.getColor("control")
    //UIManager.getColor("controlShadow")
    fillColor = color;
    this.size = size;
  }
  public void paintIcon(Component c, Graphics g, int x, int y) {
    if (fillColor != null) {
      g.setColor(fillColor);
      g.drawRect(x, y, size - 1, size - 1);
    }
  }
  public int getIconWidth() {
    return size;
  }
  public int getIconHeight() {
    return size;
  }
}