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