// SortedDataTable package org.javamoney.examples.ez.common.gui.table; import static org.javamoney.examples.ez.common.CommonIconKeys.SORT_COLUMN_DOWN; import static org.javamoney.examples.ez.common.CommonIconKeys.SORT_COLUMN_UP; import static java.awt.Cursor.HAND_CURSOR; import static java.awt.Cursor.getDefaultCursor; import static java.awt.Cursor.getPredefinedCursor; import static java.awt.event.MouseEvent.BUTTON1; import static javax.swing.SwingConstants.CENTER; import static javax.swing.SwingConstants.LEFT; import java.awt.Component; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.util.Collections; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; /** * This class facilitates using a table and the elements that the table * displays. This class maintains its own data list and facilitates storing, * accessing, and sorting those elements. Columns that can be sorted will * respond to mouse clicks on the column's header, which will invoke a sort and * cause the table to redisplay the rows. * * @param <E> The type of elements that the table will store and display. */ public abstract class SortedDataTable<E> extends DataTable<E> { /** * Constructs a new table. * * @param columns The table columns. * @param model The table model. * @param comparator The comparator that sort. */ public SortedDataTable(String[] columns, DefaultTableModel model, DataTableComparator<E> comparator) { super(columns, model); setComparator(comparator); setSortableColumns(null); setRendererForHeaders(new SortRenderController()); // Add listeners. getTableHeader().addMouseListener(new MouseController()); getTableHeader().addMouseMotionListener(new MouseController()); } ////////////////////////////////////////////////////////////////////////////// // Start of protected methods. ////////////////////////////////////////////////////////////////////////////// /** * This method returns the object that compares the table's data. * * @return The object that compares the table's data. */ protected final DataTableComparator<E> getComparator() { return itsComparator; } /** * This method sets the columns that can be sorted. A value of null indicates * that all columns can be sorted. * * @param columns An array of columns. */ protected final void setSortableColumns(int[] columns) { itsSortableColumns = columns; } /** * This method sorts the elements. */ protected final void sort() { Collections.sort(getList(), getComparator()); } ////////////////////////////////////////////////////////////////////////////// // Start of private methods. ////////////////////////////////////////////////////////////////////////////// private boolean canSortColumn(int column) { boolean result = false; if(getSortableColumns() == null) { result = true; } else { for(int len = 0; len < getSortableColumns().length; ++len) { if(column == getSortableColumns()[len]) { result = true; break; } } } return result; } private int[] getSortableColumns() { return itsSortableColumns; } private void setComparator(DataTableComparator<E> comparator) { itsComparator = comparator; } ////////////////////////////////////////////////////////////////////////////// // Start of inner classes. ////////////////////////////////////////////////////////////////////////////// private class MouseController extends MouseAdapter implements MouseMotionListener { public void mouseDragged(MouseEvent event) { mouseEntered(event); } @Override public void mouseEntered(MouseEvent event) { int column = getColumnIndexAtX(event.getPoint().x); if(canSortColumn(column) == true) { getTableHeader().setCursor(getPredefinedCursor(HAND_CURSOR)); } else { getTableHeader().setCursor(getDefaultCursor()); } } @Override public void mouseExited(MouseEvent event) { getTableHeader().setCursor(getDefaultCursor()); } @Override public void mouseClicked(MouseEvent event) { if(event.getButton() == BUTTON1) { int column = getColumnModel().getColumnIndexAtX(event.getX()); column = getIndexForColumn(column); if(canSortColumn(column) == true) { // Has the column already been selected? If so, then flip the invert // sort switch. if(getComparator().getColumn() == column) { getComparator().setInvertSort(!getComparator().invertSort()); } getComparator().setColumn(column); getTableHeader().repaint(); display(); } } } public void mouseMoved(MouseEvent event) { mouseEntered(event); } } private class SortRenderController implements TableCellRenderer { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JLabel label = (JLabel)getDefaultHeaderRenderer().getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); column = getIndexForColumn(column); label.setHorizontalAlignment(CENTER); label.setHorizontalTextPosition(LEFT); // Icon. if(getComparator().getColumn() == column) { if(getComparator().invertSort() == true) { label.setIcon(SORT_COLUMN_UP.getIcon()); } else { label.setIcon(SORT_COLUMN_DOWN.getIcon()); } label.setText("<html><b>" + label.getText() + "</b></html>"); } return label; } } ////////////////////////////////////////////////////////////////////////////// // Start of class members. ////////////////////////////////////////////////////////////////////////////// private DataTableComparator<E> itsComparator; private int[] itsSortableColumns; }