import java.awt.BorderLayout; import java.awt.Dimension; import java.util.Date; import java.util.Locale; import java.util.Vector; import javax.swing.JTable; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.table.DefaultTableModel; import javax.swing.table.JTableHeader; import javax.swing.table.TableModel; /** * A program that illustrates the use of TableSorter. * * Invoke with a single numeric argument for the table type: * * 0 - dates only, default table model * 1 - strings only, default table model * 2 - dates and strings, default table model * 3 - dates only, extended table model * 4 - strings only, extended table model * 5 - dates and strings, extended table model * * Copyright 2004, Bennett Business Solutions, Inc. * email: kbennett at bbsinc.biz */ public class TableSorterTest extends JFrame { static private long now = System.currentTimeMillis(); static private long millisInDay = 1000 * 60 * 60 * 24; static private Date today = new Date(now); static private Date yesterday = new Date(now - millisInDay); static private Date tomorrow = new Date(now + millisInDay); static private Date dayAfterTomorrow = new Date(now + (2 * millisInDay)); static private String s_o = "ooooo - Unicode value: " + (int) 'o'; static private String s_oe = "ššššš - Unicode value: " + (int) 'š'; static private String s_O = "OOOOO - Unicode value: " + (int) 'O'; static private String s_OE = "…………… - Unicode value: " + (int) '…'; static private String s_A = "AAAAA - Unicode value: " + (int) 'A'; static private String s_a = "aaaaa - Unicode value: " + (int) 'a'; static private String s_Z = "ZZZZZ - Unicode value: " + (int) 'Z'; static private String s_z = "zzzzz - Unicode value: " + (int) 'z'; static final Object [][] dateTableData = { {tomorrow}, {yesterday}, {today}, {dayAfterTomorrow} }; static final Object [] dateColumnNames = { "A Date" }; static final Class [] dateTableClasses = { Date.class }; static final int dateTableWidth = 500; static final int dateTableHeight = 80; static final Object [][] stringTableData = { { s_A }, { s_a }, { s_o }, { s_oe }, { s_O }, { s_OE }, { s_z }, { s_Z } }; static final Object [] stringColumnNames = { "A String" }; static final Class [] stringTableClasses = { String.class }; static final int stringTableWidth = 500; static final int stringTableHeight = 160; static final Object [][] intDateStringTableData = { { new Integer(1), today, s_o }, { new Integer(1), today, s_oe }, { new Integer(1), tomorrow, s_o }, { new Integer(1), tomorrow, s_oe }, { new Integer(1), tomorrow, s_O }, { new Integer(1), tomorrow, s_OE }, { new Integer(2), tomorrow, s_OE }, }; static final Object [] intDateStringColumnNames = { "An Integer", "A Date", "A String" }; static final Class [] intDateStringTableClasses = { Integer.class, Date.class, String.class }; static final int intDateStringTableWidth = 700; static final int intDateStringTableHeight = 120; static private class TableConfigData { public String description; public Object [][] tableData; public Object [] columnNames; public Class [] classes; public int tableWidth; public int tableHeight; public boolean useDefaultTableModel; public boolean useNewTableSorter; public TableConfigData( String description, Object [][] tableData, Object [] columnNames, Class [] classes, int tableWidth, int tableHeight, boolean useDefaultTableModel, boolean useNewTableSorter) { this.description = description; this.tableData = tableData; this.columnNames = columnNames; this.classes = classes; this.tableWidth = tableWidth; this.tableHeight = tableHeight; this.useDefaultTableModel = useDefaultTableModel; this.useNewTableSorter = useNewTableSorter; } } static private TableConfigData[] configs = new TableConfigData[] { new TableConfigData( "Dates using DefaultTableModel", dateTableData, dateColumnNames, dateTableClasses, dateTableWidth, dateTableHeight, true, true), new TableConfigData( "Dates using subclass of DefaultTableModel", dateTableData, dateColumnNames, dateTableClasses, dateTableWidth, dateTableHeight, false, true), new TableConfigData( "Strings using original TableModel", stringTableData, stringColumnNames, stringTableClasses, stringTableWidth, stringTableHeight, true, false), new TableConfigData( "Strings using new table model", stringTableData, stringColumnNames, stringTableClasses, stringTableWidth, stringTableHeight, true, true), new TableConfigData( "3 Column Sort", intDateStringTableData, intDateStringColumnNames, intDateStringTableClasses, intDateStringTableWidth, intDateStringTableHeight, false, true), new TableConfigData( null, intDateStringTableData, intDateStringColumnNames, intDateStringTableClasses, intDateStringTableWidth, intDateStringTableHeight, false, true), }; /** * Returns the table model used for this table type. */ private static TableModel getTableModel(int sampleNum) { final TableConfigData config = configs[sampleNum]; if (config.useDefaultTableModel) { System.out.println("Using DefaultTableModel."); return new DefaultTableModel( config.tableData, config.columnNames); } else { System.out.println("Using subclass of DefaultTableModel."); // We use here the Java shorthand for creating a subclass // This creates a class that extends DefaultTableModel, // and passes the arguments getSampleData() and // getColumnNames() to the constructor of // DefaultTableModel (which is the superclass of our // newly created class). return new DefaultTableModel( config.tableData, config.columnNames) { // The DefaultTableModel returns Object as the class // of all table values. We want to be more specific. // We want TableSorter to recognize the classes as // implementors of Comparable, so the sort will // respect the data type and not just sort as // strings. Class [] classes = config.classes; public Class getColumnClass(int column) { return classes[column]; } }; } } /** * Constructor for this class, this method creates the models and * components, places them in the frame, and packs the frame. */ public TableSorterTest(int sampleNum) { super("TableSorter Test - " + configs[sampleNum].description); final TableConfigData config = configs[sampleNum]; setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); TableModel innerTableModel = getTableModel(sampleNum); JTable table; if (config.useNewTableSorter) { // Create the TableSorter with the sample table model wrapped // inside it. NewTableSorter sorter = new NewTableSorter(innerTableModel); // Uncomment the following line to use the arrow icon provided // in the original TableSorter class from Sun. // sorter.setUsingClassicArrow(true); // Create the table, specifying the TableSorter as its model. table = new JTable(sorter); // Get the table header from the table. JTableHeader header = table.getTableHeader(); // Set the table's header in the TableSorter so it knows to // listen to mouse clicks and change the appearance of the // table header when necessary. sorter.setTableHeader(header); } else { // Create the TableSorter with the sample table model wrapped // inside it. TableSorter sorter = new TableSorter(innerTableModel); // Uncomment the following line to use the arrow icon provided // in the original TableSorter class from Sun. // sorter.setUsingClassicArrow(true); // Create the table, specifying the TableSorter as its model. table = new JTable(sorter); // Get the table header from the table. JTableHeader header = table.getTableHeader(); // Set the table's header in the TableSorter so it knows to // listen to mouse clicks and change the appearance of the // table header when necessary. sorter.setTableHeader(header); } // Just for illustrative purposes, print the cell renderers' // toString() values. for (int i = 0; i < table.getModel().getColumnCount(); i++) { System.out.println("\nColumn #" + i + "'s renderer is : " + table.getCellRenderer(0, i) + "\n"); } // Set the table size to fit the data table.setPreferredScrollableViewportSize( new Dimension(config.tableWidth, config.tableHeight)); getContentPane().add( new JScrollPane(table), BorderLayout.CENTER); pack(); } public static void main(String [] args) { // Tell the system to use the German locale so that it // will properly sort the accented vowels. Locale.setDefault(Locale.GERMANY); // Uncomment this to print to stdout the locales supported by // collators. // Locale [] locales = // java.text.Collator.getInstance().getAvailableLocales(); // for (int i = 0; i < locales.length; i++) { // System.out.println(locales[i]); // } int sampleNum = 0; if (args.length > 0) { try { sampleNum = Integer.parseInt(args[0]); if (sampleNum < 0 || sampleNum > 5) { sampleNum = 0; } } catch (NumberFormatException nfe) { // Do nothing; use default value of 0 } } new TableSorterTest(sampleNum).setVisible(true); } }