001 package util.swing; 002 003 import javax.swing.*; 004 import javax.swing.event.*; 005 import javax.swing.table.*; 006 import javax.swing.border.*; 007 008 import java.awt.Dimension; 009 010 import data.Value; 011 import data.NumberValue; 012 013 import resource.util.ResourceManager; 014 015 /** 016 * A {@link JTable} that prefers models that are lists of records. A <code>JAbstractTable</code> always must 017 * be used together with an {@link util.swing.AbstractTableModel}. 018 * 019 * <p>Also <code>JAbstractTable</code> supports one selection observer which is basically an int value that 020 * will always contain the index of the currently selected record in the table. Setting up such an observer is 021 * quite straightforward:</p> 022 * 023 * <pre> 024 * int[] anSelection = new int[1]; 025 * 026 * JAbstractTable jat = new JAbstractTable (...); 027 * jat.{@link #setSelectionObserver setSelectionObserver} (anSelection); 028 * </pre> 029 * 030 * <p>To use this observer write code like the following:</p> 031 * 032 * <pre> 033 * ... 034 * Object oSelectedRecord = ((util.swing.AbstractTableModel) jat.getModel()).getRecord (anSelection[0]); 035 * if (oSelectedRecord != null) { 036 * ... 037 * } 038 * </pre> 039 * 040 * <p>Note that although you only use the actual int value, you still have to set up an array of int values. 041 * The current selection will always be written to the first element in this array, no matter how long the 042 * actual array is.</p> 043 * 044 * <p><b>Note:</b> This class is not meant to be serialized!</p> 045 * 046 * @author Steffen Zschaler 047 * @version 2.0 28/07/1999 048 * @since v2.0 049 * 050 * @see util.swing.AbstractTableModel 051 * @see TableEntryDescriptor 052 */ 053 public class JAbstractTable extends JTable { 054 055 /** 056 * The current selection observer. 057 * 058 * @serial This class is not meant to be serialized! 059 */ 060 private int[] m_anSelection; 061 062 /** 063 * The monitor that synchronizes access to the selection observer. As this class is not meant to be 064 * serialized, no care needs to be taken. 065 */ 066 private final transient Object m_oSelectionLock = new Object(); 067 068 /** 069 * Holds the currently selected Column in Header 070 */ 071 private Object[] m_aoSelectedColumn = new Object[2]; 072 073 /** 074 * The current {@link util.swing.AbstractTableModel} 075 */ 076 private AbstractTableModel atm; 077 078 /** 079 * Creates the TableHeader and enables it to display sorting icons (arrows up and down) 080 */ 081 public DefaultTableCellRenderer createHeader() { 082 return new DefaultTableCellRenderer() { 083 public java.awt.Component getTableCellRendererComponent(JTable table, Object value, 084 boolean isSelected, boolean hasFocus, int row, int column) { 085 086 JLabel label = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, 087 row, column); 088 label.setBorder(new javax.swing.border.EtchedBorder()); 089 label.setHorizontalAlignment(JLabel.CENTER); 090 label.setPreferredSize(new Dimension(0, 20)); 091 label.setBackground(java.awt.Color.lightGray); 092 label.setFont(new java.awt.Font("SansSerif", java.awt.Font.BOLD, 12)); 093 if (m_aoSelectedColumn[0] != null) { 094 if (column == ((Integer)m_aoSelectedColumn[0]).intValue()) { 095 if (((Boolean)m_aoSelectedColumn[1]).booleanValue()) { 096 setIcon(DOWN); 097 } else { 098 setIcon(UP); 099 } 100 } else { 101 setIcon(null); 102 } 103 } 104 105 setValue(value.toString()); 106 return label; 107 } 108 }; 109 } 110 111 /** 112 * Construct a new JAbstractTable that is based on an {@link util.swing.AbstractTableModel}. 113 * 114 * @param atm the TableModel to be used with this table. 115 */ 116 public JAbstractTable(AbstractTableModel atm) { 117 super(); 118 this.atm = atm; 119 getTableHeader().setReorderingAllowed(false); 120 121 TableSorter sorter = new TableSorter(atm); 122 sorter.addMouseListenerToHeaderInTable(this, m_aoSelectedColumn); 123 setModel(sorter); 124 125 // Rendering the TableHeader 126 getTableHeader().setDefaultRenderer(createHeader()); 127 128 setDefaultRenderer(String.class, new DefaultTableCellRenderer()); 129 setDefaultRenderer(Value.class, new DefaultTableCellRenderer()); 130 131 TableCellRenderer tcr = new DefaultTableCellRenderer(); 132 ((JLabel)tcr).setHorizontalAlignment(JLabel.RIGHT); 133 134 setDefaultRenderer(NumberValue.class, tcr); 135 136 setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 137 138 m_anSelection = new int[] { 139 -1}; 140 getSelectionModel().addListSelectionListener(new ListSelectionListener() { 141 public void valueChanged(ListSelectionEvent lse) { 142 synchronized (m_oSelectionLock) { 143 m_anSelection[0] = getSelectedRow(); 144 } 145 } 146 }); 147 148 TableEntryDescriptor ted = atm.getEntryDescriptor(); 149 TableColumnModel tcm = getColumnModel(); 150 151 for (int i = 0; i < ted.getColumnCount(); i++) { 152 TableColumn tc = tcm.getColumn(i); 153 154 tc.setCellRenderer(ted.getCellRenderer(i)); 155 tc.setCellEditor(ted.getCellEditor(i)); 156 } 157 158 } 159 160 public void initialize() { 161 m_aoSelectedColumn = new Object[2]; 162 getTableHeader().setDefaultRenderer(createHeader()); 163 ((TableSorter)getModel()).addMouseListenerToHeaderInTable(this, m_aoSelectedColumn); 164 165 TableEntryDescriptor ted = atm.getEntryDescriptor(); 166 TableColumnModel tcm = getColumnModel(); 167 168 for (int i = 0; i < ted.getColumnCount(); i++) { 169 TableColumn tc = tcm.getColumn(i); 170 171 tc.setCellRenderer(ted.getCellRenderer(i)); 172 tc.setCellEditor(ted.getCellEditor(i)); 173 } 174 } 175 176 /** 177 * Set a selection observer for this table. The first element of the given array will henceforward 178 * contain the index of the currently selected record. 179 * 180 * @param anSelection the selection observer 181 * 182 * @override Never 183 */ 184 public void setSelectionObserver(int[] anSelection) { 185 synchronized (m_oSelectionLock) { 186 anSelection[0] = getSelectedRow(); 187 m_anSelection = anSelection; 188 } 189 } 190 191 /** 192 * Icon "Down" 193 */ 194 private static final ImageIcon DOWN = new ImageIcon(ResourceManager.getInstance().getResource( 195 ResourceManager.RESOURCE_GIF, "icon.icon_down_16x16")); 196 197 /** 198 * Icon "Up" 199 */ 200 private static final ImageIcon UP = new ImageIcon(ResourceManager.getInstance().getResource( 201 ResourceManager.RESOURCE_GIF, "icon.icon_up_16x16")); 202 203 /** 204 * return the {@link util.swing.AbstractTableModel} 205 * @return atm the current AbstractTableModel 206 */ 207 public AbstractTableModel getAbstractTableModel() { 208 return atm; 209 } 210 }