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 }