source: trunk/gli/src/org/greenstone/gatherer/gui/MetadataValueTablePane.java@ 12043

Last change on this file since 12043 was 12043, checked in by kjdon, 18 years ago

made the table cell renderer work properly if the user has changed the positions of the columns

  • Property svn:keywords set to Author Date Id Revision
File size: 15.3 KB
Line 
1/**
2 *############################################################################
3 * A component of the Greenstone Librarian Interface, part of the Greenstone
4 * digital library suite from the New Zealand Digital Library Project at the
5 * University of Waikato, New Zealand.
6 *
7 * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
8 *
9 * Copyright (C) 2005 New Zealand Digital Library Project
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *############################################################################
25 */
26
27package org.greenstone.gatherer.gui;
28
29
30import java.awt.*;
31import java.awt.event.*;
32import java.io.*;
33import javax.swing.*;
34import javax.swing.event.*;
35import javax.swing.table.*;
36import org.greenstone.gatherer.Configuration;
37import org.greenstone.gatherer.Dictionary;
38import org.greenstone.gatherer.collection.CollectionTreeNode;
39import org.greenstone.gatherer.metadata.MetadataChangedListener;
40import org.greenstone.gatherer.metadata.MetadataElement;
41import org.greenstone.gatherer.metadata.MetadataTools;
42import org.greenstone.gatherer.metadata.MetadataValue;
43import org.greenstone.gatherer.metadata.MetadataValueTableEntry;
44import org.greenstone.gatherer.metadata.MetadataValueTableModel;
45import org.greenstone.gatherer.metadata.MetadataXMLFileManager;
46import org.greenstone.gatherer.util.JarTools;
47import org.greenstone.gatherer.util.Utility;
48
49
50public class MetadataValueTablePane
51 extends JPanel
52{
53 private MetadataValueTable metadata_value_table = null;
54 /** Used to display either the MetadataValueTable (when files are selected) or a placeholder panel */
55 private CardLayout card_layout = null;
56 /** The name of the panel containing the metadata value table */
57 private String METADATA_VALUE_TABLE_CARD = "";
58 /** The name of the panel containing the "no metadata available" placeholder */
59 private String NO_METADATA_AVAILABLE_CARD = "No metadata available";
60 /** The name of the panel containing the "no files selected" placeholder */
61 private String NO_FILES_SELECTED_CARD = "No files selected";
62
63
64 public MetadataValueTablePane()
65 {
66 super();
67
68 metadata_value_table = new MetadataValueTable();
69
70 JScrollPane metadata_value_table_scroll = new JScrollPane(metadata_value_table);
71 metadata_value_table_scroll.getViewport().setBackground(Configuration.getColor("coloring.collection_tree_background", false));
72 metadata_value_table_scroll.setOpaque(true);
73
74 JPanel metadata_value_table_pane = new JPanel();
75 metadata_value_table_pane.setLayout(new BorderLayout());
76 metadata_value_table_pane.add(metadata_value_table_scroll, BorderLayout.CENTER);
77
78 JLabel no_metadata_available_label = new JLabel();
79 no_metadata_available_label.setHorizontalAlignment(JLabel.CENTER);
80 no_metadata_available_label.setOpaque(false);
81 no_metadata_available_label.setVerticalAlignment(JLabel.CENTER);
82 Dictionary.registerText(no_metadata_available_label, "EnrichPane.No_Metadata");
83
84 JPanel no_metadata_available_pane = new JPanel();
85 no_metadata_available_pane.setLayout(new BorderLayout());
86 no_metadata_available_pane.add(no_metadata_available_label, BorderLayout.CENTER);
87
88 JLabel no_files_selected_label = new JLabel();
89 no_files_selected_label.setHorizontalAlignment(JLabel.CENTER);
90 no_files_selected_label.setOpaque(false);
91 no_files_selected_label.setVerticalAlignment(JLabel.CENTER);
92 Dictionary.registerText(no_files_selected_label, "EnrichPane.No_File");
93
94 JPanel no_files_selected_pane = new JPanel();
95 no_files_selected_pane.setLayout(new BorderLayout());
96 no_files_selected_pane.add(no_files_selected_label, BorderLayout.CENTER);
97
98 card_layout = new CardLayout();
99
100 this.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
101 this.setFont(Configuration.getFont("general.font", false));
102 this.setLayout(card_layout);
103 this.add(metadata_value_table_pane, METADATA_VALUE_TABLE_CARD);
104 this.add(no_metadata_available_pane, NO_METADATA_AVAILABLE_CARD);
105 this.add(no_files_selected_pane, NO_FILES_SELECTED_CARD);
106 }
107
108
109 public void addMetadataValueTableListSelectionListener(ListSelectionListener list_selection_listener)
110 {
111 metadata_value_table.getSelectionModel().addListSelectionListener(list_selection_listener);
112 }
113
114
115 public void addMetadataValueTableMouseListener(MouseListener mouse_listener)
116 {
117 metadata_value_table.addMouseListener(mouse_listener);
118 }
119
120
121 public void addMetadataValueTextFieldDocumentListener(DocumentListener document_listener)
122 {
123 metadata_value_table.getMetadataValueTextField().getDocument().addDocumentListener(document_listener);
124 }
125
126
127 public void addMetadataValueTextFieldKeyListener(KeyListener key_listener)
128 {
129 metadata_value_table.getMetadataValueTextField().addKeyListener(key_listener);
130 }
131
132
133 public MetadataValueTableEntry getSelectedMetadataValueTableEntry()
134 {
135 return metadata_value_table.getSelectedMetadataValueTableEntry();
136 }
137
138
139 public boolean isMouseEventForInheritedMetadataValueTableColumn(MouseEvent mouse_event)
140 {
141 return metadata_value_table.isMouseEventForInheritedMetadataValueTableColumn(mouse_event);
142 }
143
144
145 public void setMetadataValueTextFieldValue(String metadata_value_string)
146 {
147 metadata_value_table.setMetadataValueTextFieldValue(metadata_value_string);
148 }
149
150
151 public void stopEditingAndAddBlankRowForSelectedMetadataElement()
152 {
153 metadata_value_table.stopEditing();
154 metadata_value_table.addBlankRowForSelectedMetadataElement();
155 }
156
157
158 public void stopEditingAndRebuild(CollectionTreeNode[] file_nodes)
159 {
160 metadata_value_table.stopEditing();
161 metadata_value_table.rebuild(file_nodes);
162
163 // If no files are selected display the "no file selected" card
164 if (file_nodes == null) {
165 card_layout.show(this, NO_FILES_SELECTED_CARD);
166 }
167 // If the metadata value table is empty display the "no metadata available" card
168 else if (metadata_value_table.getRowCount() == 0) {
169 card_layout.show(this, NO_METADATA_AVAILABLE_CARD);
170 }
171 // Otherwise display the card with the metadata value table
172 else {
173 card_layout.show(this, METADATA_VALUE_TABLE_CARD);
174 }
175 }
176
177
178 private class MetadataValueTable
179 extends JTable
180 implements MetadataChangedListener
181 {
182 private int MINIMUM_TABLE_HEADER_SIZE = 15;
183
184 private MetadataValueTableModel metadata_value_table_model = null;
185 private JTextField metadata_value_text_field = new JTextField();
186
187
188 public MetadataValueTable()
189 {
190 // Create the model for the table
191 metadata_value_table_model = new MetadataValueTableModel();
192 setModel(metadata_value_table_model);
193
194 // We allow only one row in the table to be selected at a time
195 setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
196
197 // We use our own editor for the value column so we have easy access to the underlying text field
198 setDefaultEditor(String.class, new DefaultCellEditor(metadata_value_text_field));
199
200 // We need to listen for double clicks on the text field to open the editor dialog
201 metadata_value_text_field.addMouseListener(new MetadataValueTextFieldMouseListener());
202 metadata_value_text_field.setBorder(null);
203
204 // We need to listen for key presses so we can catch Enter presses
205 addKeyListener(new MetadataValueTableKeyListener());
206
207 // We need to listen for metadata changes so we can rebuild the table
208 MetadataXMLFileManager.addMetadataChangedListener(this);
209
210 // We also have to ensure that the table column header hasn't gone on a severe Jenny Craig binge and has somehow lost 7/8th of its component size
211 JTableHeader table_header = getTableHeader();
212 Dimension table_header_preferred_size = table_header.getPreferredSize();
213 if (table_header_preferred_size.height < MINIMUM_TABLE_HEADER_SIZE) {
214 table_header_preferred_size.setSize(table_header_preferred_size.width, MINIMUM_TABLE_HEADER_SIZE);
215 table_header.setPreferredSize(table_header_preferred_size);
216 }
217
218 // Set the size of the table columns: 2/7 for element, 5/7 for value (actual numbers don't matter)
219 TableColumnModel column_model = getColumnModel();
220 TableColumn inherited_column = column_model.getColumn(0);
221 inherited_column.setMinWidth(25);
222 inherited_column.setPreferredWidth(25);
223 inherited_column.setMaxWidth(25);
224 TableColumn element_column = column_model.getColumn(1);
225 element_column.setPreferredWidth(200);
226 TableColumn value_column = column_model.getColumn(2);
227 value_column.setPreferredWidth(500);
228
229 // Use our own renderer for the table cells
230 MetadataValueTableCellRenderer metadata_value_table_cell_renderer = new MetadataValueTableCellRenderer();
231 inherited_column.setCellRenderer(metadata_value_table_cell_renderer);
232 element_column.setCellRenderer(metadata_value_table_cell_renderer);
233 value_column.setCellRenderer(metadata_value_table_cell_renderer);
234 }
235
236
237 private void addBlankRowForSelectedMetadataElement()
238 {
239 // Add a blank entry for the selected metadata element, then switch to it
240 MetadataElement selected_metadata_element = getSelectedMetadataValueTableEntry().getMetadataElement();
241 int blank_row = metadata_value_table_model.addBlankRowForMetadataElement(selected_metadata_element);
242 changeSelection(blank_row, 2, false, false);
243 }
244
245
246 private JTextField getMetadataValueTextField()
247 {
248 return metadata_value_text_field;
249 }
250
251
252 private MetadataValueTableEntry getSelectedMetadataValueTableEntry()
253 {
254 return metadata_value_table_model.getMetadataValueTableEntry(getSelectedRow());
255 }
256
257
258 private boolean isMouseEventForInheritedMetadataValueTableColumn(MouseEvent mouse_event)
259 {
260 return (columnAtPoint(mouse_event.getPoint()) == 0);
261 }
262
263
264 public void metadataChanged(CollectionTreeNode[] file_nodes)
265 {
266 rebuild(file_nodes);
267 }
268
269
270 private void rebuild(CollectionTreeNode[] file_nodes)
271 {
272 // Note the metadata value table entry currently selected
273 MetadataValueTableEntry selected_metadata_value_table_entry = getSelectedMetadataValueTableEntry();
274
275 // We don't want a lot of ListSelectionEvents while the table is rebuilding
276 clearSelection();
277
278 // Rebuild the metadata value table model
279 metadata_value_table_model.rebuild(file_nodes);
280
281 // Restore the metadata value table entry selection
282 if (selected_metadata_value_table_entry != null) {
283 int row_to_select = metadata_value_table_model.findMetadataValueTableEntryToSelect(selected_metadata_value_table_entry);
284 changeSelection(row_to_select, 2, false, false);
285 }
286 }
287
288
289 private void setMetadataValueTextFieldValue(String metadata_value_string)
290 {
291 metadata_value_text_field.setText(metadata_value_string);
292 metadata_value_text_field.requestFocus();
293 }
294
295
296 private void stopEditing()
297 {
298 // Save the current value in the text field, then remove the editor so it doesn't get saved again
299 TableCellEditor table_cell_editor = getCellEditor();
300 if (table_cell_editor != null) {
301 Object new_metadata_value = table_cell_editor.getCellEditorValue();
302 setValueAt(new_metadata_value, editingRow, editingColumn);
303 removeEditor();
304 }
305 }
306
307
308 private class MetadataValueTableCellRenderer
309 extends DefaultTableCellRenderer
310 {
311 /** Returns the default table cell renderer.
312 * @param table The <strong>JTable</strong>.
313 * @param value The value to assign to the cell at [row, column] as an <strong>Object</strong>.
314 * @param isSelected <i>true</i> if cell is selected.
315 * @param hasFocus <i>true</i> if cell has focus.
316 * @param row The row of the cell to render as an <i>int</i>.
317 * @param column The column of the cell to render as an <i>int</i>.
318 * @return The default table cell renderer <strong>Component</strong>.
319 */
320 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
321 {
322 JComponent component = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
323
324 int real_column = table.convertColumnIndexToModel(column);
325 // First column: inherited metadata icon
326 if (real_column == 0 && value != null) {
327 component = new JLabel(JarTools.getImage("upfolder.gif"));
328 }
329
330 // Make sure the focus always stay in the value cell of the selected row
331 if (real_column == 2 && isSelected) {
332 table.editCellAt(row, column);
333 if (table.isEditing()) {
334 table.getEditorComponent().requestFocus();
335 }
336 }
337
338 // Set up the component
339 component.setOpaque(true);
340
341 // Foreground
342 if (metadata_value_table_model.isCommon(row)) {
343 component.setForeground(Color.black);
344 }
345 else {
346 component.setForeground(Color.gray);
347 }
348
349 // Background
350 if (isSelected) {
351 component.setBackground(Configuration.getColor("coloring.workspace_heading_background", true));
352 }
353 else {
354 if (real_column < 2) {
355 component.setBackground(Configuration.getColor("coloring.collection_heading_background", true));
356 }
357 else {
358 component.setBackground(Configuration.getColor("coloring.collection_tree_background", true));
359 }
360 }
361
362 // The value column of cells never paints focus
363 if (real_column == 2) {
364 component.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
365 }
366
367 // We set a tooltip over the element column containing the definition of the element
368 if (value instanceof MetadataElement) {
369 String interface_language_code = Configuration.getLanguage();
370 String metadata_element_definition = MetadataTools.getMetadataElementAttribute((MetadataElement) value, "definition", interface_language_code, "en");
371 if (metadata_element_definition != null) {
372 component.setToolTipText(Utility.formatHTMLWidth(metadata_element_definition, 60));
373 }
374 }
375
376 return component;
377 }
378 }
379
380
381 private class MetadataValueTableKeyListener
382 extends KeyAdapter
383 {
384 /** Gives notification of key events on the text field */
385 public void keyPressed(KeyEvent key_event)
386 {
387 // Enter: save the current value then add a blank row for the selected metadata element
388 if (key_event.getKeyCode() == KeyEvent.VK_ENTER) {
389 // ...but not for extracted metadata elements of course
390 MetadataValueTableEntry metadata_value_table_entry = getSelectedMetadataValueTableEntry();
391 if (!metadata_value_table_entry.getMetadataElement().isExtractedMetadataElement()) {
392 addBlankRowForSelectedMetadataElement();
393 }
394
395 // We do not want this event to be processed by the table also
396 key_event.consume();
397 }
398 }
399 }
400
401
402 private class MetadataValueTextFieldMouseListener
403 extends MouseAdapter
404 {
405 public void mouseClicked(MouseEvent mouse_event)
406 {
407 // Double-click: pop up an editor dialog for large metadata values
408 if (mouse_event.getClickCount() == 2) {
409 EditorDialog editor_dialog = new EditorDialog();
410 String new_metadata_value_string = editor_dialog.display(metadata_value_text_field.getText());
411 if (new_metadata_value_string != null) {
412 setMetadataValueTextFieldValue(new_metadata_value_string);
413 }
414 }
415 }
416 }
417 }
418}
Note: See TracBrowser for help on using the repository browser.