The IdentityTable now has a new method, installKeybordActions, which puts the new actions into the ActionMap. Now, whenever the actions to move forward or backward a cell are accessed, our versions will be used.
1 2 package com.vizitsolutions.identitytable; 3 4 import javax.swing.ActionMap; 5 import javax.swing.table.DefaultTableColumnModel; 6 import javax.swing.JScrollPane; 7 import javax.swing.JTable; 8 import javax.swing.JViewport; 9 import javax.swing.ListSelectionModel; 10 import javax.swing.table.TableColumn; 11 import javax.swing.table.TableColumnModel; 12 13 /** 14 * <p>$Id$</p> 15 * 16 * <p> 17 * This class maps a TableModel into two JTables, and places 18 * them into a JScrollPane. The first JTable contains n fixed 19 * columns, and represents what is commonly called a rowheader. 20 * This is placed in the rowheader area of the JScrollPane. These 21 * columns will not scroll horizontally. This is particularly 22 * useful when you have one or more columns that identify an object 23 * and several additional columns that contain attributes of the 24 * object. Placing the identifying columns in these fixed columns 25 * ensures that they are always visible while the attributes of the 26 * object are scrolled into view. 27 * </p> 28 * <p> 29 * The second JTable contains the remaining columns and is placed in 30 * the main viewport and will scroll normally. 31 * </p> 32 * 33 * @author Alex Kluge 34 * @version $Revision$, $Date$ 35 */ 36 public class IdentityTable4 extends JScrollPane 37 { 38 // These names follow those used in JTable UI delegate. 39 public static final String LEFT_ARROW_ACTION_NAME = "selectPreviousColumn"; 40 public static final String RIGHT_ARROW_ACTION_NAME = "selectNextColumn"; 41 public static final String SHIFT_TAB_ACTION_NAME = "selectPreviousColumnCell"; 42 public static final String TAB_ACTION_NAME = "selectNextColumnCell"; 43 44 private JTable mainTable; 45 private TableColumnModel mainColumnModel = new DefaultTableColumnModel(); 46 private JTable rowHeaderTable; 47 private TableColumnModel rowHeaderColumnModel = new DefaultTableColumnModel(); 48 49 /** 50 * Creates a new instance of IdentityTable 51 */ 52 public IdentityTable4(IdentityTableModel baseTableModel) 53 { 54 // Start out life as an empty scrollpane. 55 super(); 56 57 // Loop over each of the fixed columns, and create columns in the row 58 // header column model for them. 59 TableColumn column; 60 int columnCount = baseTableModel.getColumnCount(); 61 int currentColumn; 62 int identityColumnCount = baseTableModel.getIdentityColumnCount(); 63 64 for (currentColumn = 0; currentColumn<identityColumnCount; currentColumn++) 65 { 66 column = new TableColumn(currentColumn); 67 column.setHeaderValue(baseTableModel.getColumnName(currentColumn)); 68 69 rowHeaderColumnModel.addColumn(column); 70 } 71 72 // Now loop over the remaining columns, and add them to the main table's column model. 73 for (currentColumn = identityColumnCount; currentColumn<columnCount; currentColumn++) 74 { 75 column = new TableColumn(currentColumn); 76 column.setHeaderValue(baseTableModel.getColumnName(currentColumn)); 77 78 mainColumnModel.addColumn(column); 79 } 80 81 // Providing a column model here automatically sets the 82 // autoCreateColumnsFromModel flag to false. 83 rowHeaderTable = new JTable(baseTableModel, rowHeaderColumnModel); 84 rowHeaderTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 85 86 mainTable = new JTable(baseTableModel, mainColumnModel); 87 mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 88 89 // Ensure that both tables have common selections. 90 // Save the row selection model for later. 91 ListSelectionModel rowSelectionModel = mainTable.getSelectionModel(); 92 rowHeaderTable.setSelectionModel(rowSelectionModel); 93 rowHeaderTable.setPreferredScrollableViewportSize(rowHeaderTable.getPreferredSize()); 94 95 // This puts the column headers in the upper left corner above the row 96 // header columns. This is the same thing that happens when a JTable configures 97 // the containing JScrollPane. 98 setCorner(JScrollPane.UPPER_LEFT_CORNER, rowHeaderTable.getTableHeader()); 99 100 JViewport rowHeaderViewPort = new JViewport(); 101 rowHeaderViewPort.setView(rowHeaderTable); 102 setRowHeader(rowHeaderViewPort); 103 104 // Listen for resize events on the row header, and resize the main table as appropriate. 105 RowHeaderResizeListener rowHeaderResizeListener = new RowHeaderResizeListener(this, rowHeaderViewPort, 106 rowHeaderTable, mainTable); 107 rowHeaderTable.addComponentListener(rowHeaderResizeListener); 108 109 setViewportView(mainTable); 110 111 installKeybordActions(rowHeaderTable, mainTable, 112 rowSelectionModel, rowHeaderColumnModel.getSelectionModel(), 113 mainColumnModel.getSelectionModel()); 114 } 115 116 protected void installKeybordActions(JTable rowHeaderTable, final JTable mainTable, 117 ListSelectionModel rowSelectionModel, ListSelectionModel headerColumnSelectionModel, 118 ListSelectionModel mainColumnSelectionModel) 119 { 120 ActionMap rowHeaderActionmap = rowHeaderTable.getActionMap(); 121 ActionMap mainActionMap = mainTable.getActionMap(); 122 123 124 // Tab action handler, shift forward one cell, with wrapping 125 TabKeyActionHandler tabKeyActionHandler 126 = new TabKeyActionHandler(rowHeaderTable, mainTable, 127 rowSelectionModel, headerColumnSelectionModel, 128 mainColumnSelectionModel, 1, 129 true); 130 // Put the action handler into the appropriate place for both the 131 // row header and the main table. 132 rowHeaderActionmap.put(TAB_ACTION_NAME, tabKeyActionHandler); 133 mainActionMap.put(TAB_ACTION_NAME, tabKeyActionHandler); 134 135 // Right arrow action handler, shift forward one cell, no wrapping. 136 tabKeyActionHandler 137 = new TabKeyActionHandler(rowHeaderTable, mainTable, 138 rowSelectionModel, headerColumnSelectionModel, 139 mainColumnSelectionModel, 1, 140 false); 141 142 rowHeaderActionmap.put(RIGHT_ARROW_ACTION_NAME, tabKeyActionHandler); 143 mainActionMap.put(RIGHT_ARROW_ACTION_NAME, tabKeyActionHandler); 144 145 // Shift-Tab action handler, shift backward one cell, with wrapping 146 tabKeyActionHandler 147 = new TabKeyActionHandler(rowHeaderTable, mainTable, 148 rowSelectionModel, headerColumnSelectionModel, 149 mainColumnSelectionModel, -1, 150 true); 151 152 rowHeaderActionmap.put(SHIFT_TAB_ACTION_NAME, tabKeyActionHandler); 153 mainActionMap.put(SHIFT_TAB_ACTION_NAME, tabKeyActionHandler); 154 155 // Left arrow action handler, shift backward one cell, no wrapping. 156 tabKeyActionHandler 157 = new TabKeyActionHandler(rowHeaderTable, mainTable, 158 rowSelectionModel, headerColumnSelectionModel, 159 mainColumnSelectionModel, -1, 160 false); 161 162 rowHeaderActionmap.put(LEFT_ARROW_ACTION_NAME, tabKeyActionHandler); 163 mainActionMap.put(LEFT_ARROW_ACTION_NAME, tabKeyActionHandler); 164 } 165 166 public TableColumnModel getMainColumnModel() 167 { 168 return mainColumnModel; 169 } 170 171 public TableColumnModel getRowHeaderColumnModel() 172 { 173 return rowHeaderColumnModel; 174 } 175 } 176 177