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 }