1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package coras.table;
22
23 import java.awt.Component;
24 import java.awt.Container;
25 import java.awt.Dimension;
26 import java.awt.Rectangle;
27 import java.awt.event.ActionEvent;
28 import java.awt.event.ComponentAdapter;
29 import java.awt.event.ComponentEvent;
30 import java.awt.event.MouseEvent;
31 import java.awt.event.MouseMotionAdapter;
32
33 import javax.swing.AbstractAction;
34 import javax.swing.JTable;
35 import javax.swing.JViewport;
36 import javax.swing.table.DefaultTableModel;
37 import javax.swing.table.JTableHeader;
38 import javax.swing.table.TableModel;
39
40 import no.sintef.event.Concentrator;
41 import no.sintef.util.StringUtils;
42
43 import org.apache.log4j.Logger;
44
45 /***
46 * @author fvr
47 *
48 * To change the template for this generated type comment go to
49 * Window - Preferences - Java - Code Generation - Code and Comments
50 */
51 public class CorasTable extends JTable {
52
53 public static final String NAMESPACE_URI = "http://coras.sourceforge.net/schemas/coras-table-1_0.xsd"; //$NON-NLS-1$
54 public static final String PREFIX = "coras-table";
55
56 private static final Logger LOGGER = Logger.getLogger(CorasTable.class);
57
58 private static final String HTML_START = "<html>";
59 private static final String HTML_END = "</html>";
60
61 private TextAreaRenderer textAreaRenderer = new TextAreaRenderer();
62 private TextAreaEditor textAreaEditor = new TextAreaEditor();
63 private CorasTableModel tableModel = null;
64
65 public CorasTable() {
66 super();
67 initialize();
68
69 textAreaEditor.setNextAction(new AbstractAction() {
70 public void actionPerformed(ActionEvent e) {
71 editNextColumn();
72 }
73 });
74 textAreaEditor.setPrevAction(new AbstractAction() {
75 public void actionPerformed(ActionEvent e) {
76 editPrevColumn();
77 }
78 });
79 textAreaEditor.setUpAction(new AbstractAction() {
80 public void actionPerformed(ActionEvent e) {
81 editPrevRow();
82 }
83 });
84 textAreaEditor.setDownAction(new AbstractAction() {
85 public void actionPerformed(ActionEvent e) {
86 editNextRow();
87 }
88 });
89
90
91 getTableHeader().addMouseMotionListener(new MouseMotionAdapter() {
92 public void mouseDragged(MouseEvent e) {
93 updateRowHeights();
94 }
95 });
96
97 addComponentListener(new ComponentAdapter() {
98 public void componentResized(ComponentEvent e) {
99 updateRowHeights();
100 }
101 });
102 }
103
104 /***
105 *
106 */
107 protected void editNextColumn() {
108
109 int newRow = editingRow;
110 int newColumn = editingColumn + 1;
111 if (newColumn == getColumnCount()) {
112 newRow++;
113 newColumn = 0;
114 }
115 editCellAt(newRow, newColumn);
116 changeSelection(newRow, newColumn, false, false);
117 scrollToEditingCell();
118 }
119
120 protected void editPrevColumn() {
121 int newRow = editingRow;
122 int newColumn = editingColumn - 1;
123 if (newColumn == -1) {
124 newRow--;
125 newColumn = getColumnCount() - 1;
126 }
127 if (newRow != -1) {
128 editCellAt(newRow, newColumn);
129 changeSelection(newRow, newColumn, false, false);
130 scrollToEditingCell();
131 }
132 }
133
134 protected void editNextRow() {
135 int newRow = editingRow + 1;
136 editCellAt(newRow, editingColumn);
137 changeSelection(newRow, editingColumn, false, false);
138 scrollToEditingCell();
139 }
140
141 protected void editPrevRow() {
142 int newRow = editingRow - 1;
143 if (newRow != -1) {
144 editCellAt(newRow, editingColumn);
145 changeSelection(newRow, editingColumn, false, false);
146 scrollToEditingCell();
147 }
148 }
149
150 private void scrollToEditingCell() {
151 Component component = getEditorComponent();
152 if (component == null) {
153 return;
154 }
155 Rectangle bounds = component.getBounds();
156 Container parent = getParent();
157 JViewport viewport = (JViewport) parent;
158 viewport.scrollRectToVisible(bounds);
159 }
160
161 public void setTableModel(CorasTableModel newModel) {
162 tableModel = newModel;
163 if (newModel != null) {
164 setModel(newModel);
165 } else {
166 setModel(new DefaultTableModel());
167 }
168 updateRowHeights();
169 }
170
171 /***
172 *
173 */
174 public void addRow() {
175 textAreaEditor.stopCellEditing();
176 tableModel.addRow(tableModel.getRowCount());
177 }
178
179 public void insertRowAboveSelectedRow() {
180 textAreaEditor.stopCellEditing();
181 int rowIndex = getSelectedRow();
182 if (rowIndex == -1)
183 rowIndex = 0;
184 tableModel.addRow(rowIndex);
185 }
186
187 public void insertRowBelowSelectedRow() {
188 textAreaEditor.stopCellEditing();
189 int rowIndex = getSelectedRow() + 1;
190 if (rowIndex == 0)
191 rowIndex = tableModel.getRowCount();
192 tableModel.addRow(rowIndex);
193 }
194
195 public void deleteSelectedRow() {
196 textAreaEditor.cancelCellEditing();
197 tableModel.deleteRow(getSelectedRow());
198 }
199
200 private void initialize() {
201 this.setCellSelectionEnabled(true);
202 this.setDefaultRenderer(String.class, textAreaRenderer);
203 this.setDefaultEditor(String.class, textAreaEditor);
204 }
205
206 private Concentrator updateConcentrator = new Concentrator(100, new Runnable() {
207 public void run() {
208 doUpdateRowHeights();
209 }
210 });
211
212 /***
213 *
214 */
215 protected void updateRowHeights() {
216 updateConcentrator.fireEvent();
217 }
218
219 private void doUpdateRowHeights() {
220 TableModel model = getModel();
221 for (int i = 0; i < model.getRowCount(); i++) {
222 updateRowHeight(i);
223 }
224 }
225
226 protected void updateRowHeight(int row) {
227 int preferredHeight = computePreferredRowHeight(row);
228 if (preferredHeight != getRowHeight(row)) {
229 setRowHeight(row, preferredHeight);
230 }
231 }
232
233 /***
234 * @param table
235 * @param row
236 */
237 protected int computePreferredRowHeight(int row) {
238 int preferredHeight = 0;
239 TableModel tableModel = getModel();
240 int columnCount = tableModel.getColumnCount();
241 for (int col = 0; col < columnCount; col++) {
242 Rectangle rect = getCellRect(row, col, false);
243 Dimension preferredSize;
244 if (row == getEditingRow() && col == getEditingColumn()) {
245 preferredSize = textAreaEditor.getPreferredSize();
246 } else {
247 Object value = getValueAt(row, col);
248 Component c = textAreaRenderer.getTableCellRendererComponent(this, value, false, false, row, col);
249 c.setSize(rect.width, rect.height);
250 preferredSize = c.getPreferredSize();
251 }
252 if (preferredSize.height > preferredHeight)
253 preferredHeight = preferredSize.height;
254 }
255 return preferredHeight + getIntercellSpacing().height;
256 }
257
258
259 protected JTableHeader createDefaultTableHeader() {
260 return new JTableHeader(getColumnModel()) {
261 private final int MAX_LINE_LENGTH = 80;
262
263 public String getToolTipText(MouseEvent e) {
264 java.awt.Point p = e.getPoint();
265 int index = getColumnModel().getColumnIndexAtX(p.x);
266 int realIndex = getColumnModel().getColumn(index).getModelIndex();
267
268 String tip = tableModel.getColumnDescription(realIndex);
269 if (tip == null || tip.trim().length() == 0) {
270 tip = "";
271 } else {
272 tip = Messages.getString("CorasTable.column_description") + ' ' + tip.trim();
273 }
274 if (tableModel.isFixedStructure()) {
275 tip = Messages.getString("CorasTable.right_click_column_header_fixed_table") + tip;
276 } else {
277 tip = Messages.getString("CorasTable.right_click_column_header") + tip;
278 }
279 tip = HTML_START + StringUtils.addLinebreaks(tip, MAX_LINE_LENGTH) + HTML_END;
280 return tip;
281 }
282
283 };
284
285 }
286
287 }