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

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

added a tooltip for the inherited metadata icon

  • 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(Dictionary.get("EnrichPane.No_Metadata"));
79 no_metadata_available_label.setHorizontalAlignment(JLabel.CENTER);
80 no_metadata_available_label.setOpaque(false);
81 no_metadata_available_label.setVerticalAlignment(JLabel.CENTER);
82
83 JPanel no_metadata_available_pane = new JPanel();
84 no_metadata_available_pane.setLayout(new BorderLayout());
85 no_metadata_available_pane.add(no_metadata_available_label, BorderLayout.CENTER);
86
87 JLabel no_files_selected_label = new JLabel(Dictionary.get("EnrichPane.No_File"));
88 no_files_selected_label.setHorizontalAlignment(JLabel.CENTER);
89 no_files_selected_label.setOpaque(false);
90 no_files_selected_label.setVerticalAlignment(JLabel.CENTER);
91
92 JPanel no_files_selected_pane = new JPanel();
93 no_files_selected_pane.setLayout(new BorderLayout());
94 no_files_selected_pane.add(no_files_selected_label, BorderLayout.CENTER);
95
96 card_layout = new CardLayout();
97
98 this.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
99 this.setFont(Configuration.getFont("general.font", false));
100 this.setLayout(card_layout);
101 this.add(metadata_value_table_pane, METADATA_VALUE_TABLE_CARD);
102 this.add(no_metadata_available_pane, NO_METADATA_AVAILABLE_CARD);
103 this.add(no_files_selected_pane, NO_FILES_SELECTED_CARD);
104 }
105
106
107 public void addMetadataValueTableListSelectionListener(ListSelectionListener list_selection_listener)
108 {
109 metadata_value_table.getSelectionModel().addListSelectionListener(list_selection_listener);
110 }
111
112
113 public void addMetadataValueTableMouseListener(MouseListener mouse_listener)
114 {
115 metadata_value_table.addMouseListener(mouse_listener);
116 }
117
118
119 public void addMetadataValueTextFieldDocumentListener(DocumentListener document_listener)
120 {
121 metadata_value_table.getMetadataValueTextField().getDocument().addDocumentListener(document_listener);
122 }
123
124
125 public void addMetadataValueTextFieldKeyListener(KeyListener key_listener)
126 {
127 metadata_value_table.getMetadataValueTextField().addKeyListener(key_listener);
128 }
129
130
131 public MetadataValueTableEntry getSelectedMetadataValueTableEntry()
132 {
133 return metadata_value_table.getSelectedMetadataValueTableEntry();
134 }
135
136
137 public boolean isMouseEventForInheritedMetadataValueTableColumn(MouseEvent mouse_event)
138 {
139 return metadata_value_table.isMouseEventForInheritedMetadataValueTableColumn(mouse_event);
140 }
141
142
143 public void setMetadataValueTextFieldValue(String metadata_value_string)
144 {
145 metadata_value_table.setMetadataValueTextFieldValue(metadata_value_string);
146 }
147
148
149 public void stopEditingAndAddBlankRowForSelectedMetadataElement()
150 {
151 metadata_value_table.stopEditing();
152 metadata_value_table.addBlankRowForSelectedMetadataElement();
153 }
154
155
156 public void stopEditingAndRebuild(CollectionTreeNode[] file_nodes)
157 {
158 metadata_value_table.stopEditing();
159 metadata_value_table.rebuild(file_nodes);
160
161 // If no files are selected display the "no file selected" card
162 if (file_nodes == null) {
163 card_layout.show(this, NO_FILES_SELECTED_CARD);
164 }
165 // If the metadata value table is empty display the "no metadata available" card
166 else if (metadata_value_table.getRowCount() == 0) {
167 card_layout.show(this, NO_METADATA_AVAILABLE_CARD);
168 }
169 // Otherwise display the card with the metadata value table
170 else {
171 card_layout.show(this, METADATA_VALUE_TABLE_CARD);
172 }
173 }
174
175
176 private class MetadataValueTable
177 extends JTable
178 implements MetadataChangedListener
179 {
180 private int MINIMUM_TABLE_HEADER_SIZE = 15;
181
182 private MetadataValueTableModel metadata_value_table_model = null;
183 private JTextField metadata_value_text_field = new JTextField();
184
185
186 public MetadataValueTable()
187 {
188 // Create the model for the table
189 metadata_value_table_model = new MetadataValueTableModel();
190 setModel(metadata_value_table_model);
191
192 // We allow only one row in the table to be selected at a time
193 setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
194
195 // We use our own editor for the value column so we have easy access to the underlying text field
196 setDefaultEditor(String.class, new DefaultCellEditor(metadata_value_text_field));
197
198 // We need to listen for double clicks on the text field to open the editor dialog
199 metadata_value_text_field.addMouseListener(new MetadataValueTextFieldMouseListener());
200 metadata_value_text_field.setBorder(null);
201
202 // We need to listen for key presses so we can catch Enter presses
203 addKeyListener(new MetadataValueTableKeyListener());
204
205 // We need to listen for metadata changes so we can rebuild the table
206 MetadataXMLFileManager.addMetadataChangedListener(this);
207
208 // 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
209 JTableHeader table_header = getTableHeader();
210 Dimension table_header_preferred_size = table_header.getPreferredSize();
211 if (table_header_preferred_size.height < MINIMUM_TABLE_HEADER_SIZE) {
212 table_header_preferred_size.setSize(table_header_preferred_size.width, MINIMUM_TABLE_HEADER_SIZE);
213 table_header.setPreferredSize(table_header_preferred_size);
214 }
215
216 // Set the size of the table columns: 2/7 for element, 5/7 for value (actual numbers don't matter)
217 TableColumnModel column_model = getColumnModel();
218 TableColumn inherited_column = column_model.getColumn(0);
219 inherited_column.setMinWidth(25);
220 inherited_column.setPreferredWidth(25);
221 inherited_column.setMaxWidth(25);
222 TableColumn element_column = column_model.getColumn(1);
223 element_column.setPreferredWidth(200);
224 TableColumn value_column = column_model.getColumn(2);
225 value_column.setPreferredWidth(500);
226
227 // Use our own renderer for the table cells
228 MetadataValueTableCellRenderer metadata_value_table_cell_renderer = new MetadataValueTableCellRenderer();
229 inherited_column.setCellRenderer(metadata_value_table_cell_renderer);
230 element_column.setCellRenderer(metadata_value_table_cell_renderer);
231 value_column.setCellRenderer(metadata_value_table_cell_renderer);
232 }
233
234
235 private void addBlankRowForSelectedMetadataElement()
236 {
237 // Add a blank entry for the selected metadata element, then switch to it
238 MetadataElement selected_metadata_element = getSelectedMetadataValueTableEntry().getMetadataElement();
239 int blank_row = metadata_value_table_model.addBlankRowForMetadataElement(selected_metadata_element);
240 changeSelection(blank_row, 2, false, false);
241 }
242
243
244 private JTextField getMetadataValueTextField()
245 {
246 return metadata_value_text_field;
247 }
248
249
250 private MetadataValueTableEntry getSelectedMetadataValueTableEntry()
251 {
252 return metadata_value_table_model.getMetadataValueTableEntry(getSelectedRow());
253 }
254
255
256 private boolean isMouseEventForInheritedMetadataValueTableColumn(MouseEvent mouse_event)
257 {
258 return (columnAtPoint(mouse_event.getPoint()) == 0);
259 }
260
261
262 public void metadataChanged(CollectionTreeNode[] file_nodes)
263 {
264 rebuild(file_nodes);
265 }
266
267
268 private void rebuild(CollectionTreeNode[] file_nodes)
269 {
270 // Note the metadata value table entry currently selected
271 MetadataValueTableEntry selected_metadata_value_table_entry = getSelectedMetadataValueTableEntry();
272
273 // We don't want a lot of ListSelectionEvents while the table is rebuilding
274 clearSelection();
275
276 // Rebuild the metadata value table model
277 metadata_value_table_model.rebuild(file_nodes);
278
279 // Restore the metadata value table entry selection
280 if (selected_metadata_value_table_entry != null) {
281 int row_to_select = metadata_value_table_model.findMetadataValueTableEntryToSelect(selected_metadata_value_table_entry);
282 changeSelection(row_to_select, 2, false, false);
283 }
284 }
285
286
287 private void setMetadataValueTextFieldValue(String metadata_value_string)
288 {
289 metadata_value_text_field.setText(metadata_value_string);
290 metadata_value_text_field.requestFocus();
291 }
292
293
294 private void stopEditing()
295 {
296 // Save the current value in the text field, then remove the editor so it doesn't get saved again
297 TableCellEditor table_cell_editor = getCellEditor();
298 if (table_cell_editor != null) {
299 Object new_metadata_value = table_cell_editor.getCellEditorValue();
300 setValueAt(new_metadata_value, editingRow, editingColumn);
301 removeEditor();
302 }
303 }
304
305
306 private class MetadataValueTableCellRenderer
307 extends DefaultTableCellRenderer
308 {
309 /** Returns the default table cell renderer.
310 * @param table The <strong>JTable</strong>.
311 * @param value The value to assign to the cell at [row, column] as an <strong>Object</strong>.
312 * @param isSelected <i>true</i> if cell is selected.
313 * @param hasFocus <i>true</i> if cell has focus.
314 * @param row The row of the cell to render as an <i>int</i>.
315 * @param column The column of the cell to render as an <i>int</i>.
316 * @return The default table cell renderer <strong>Component</strong>.
317 */
318 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
319 {
320 JComponent component = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
321
322 int real_column = table.convertColumnIndexToModel(column);
323 // First column: inherited metadata icon
324 if (real_column == 0 && value != null) {
325 component = new JLabel(JarTools.getImage("upfolder.gif"));
326 component.setToolTipText(Dictionary.get("EnrichPane.InheritedMetadata_Tooltip"));
327 }
328
329 // Make sure the focus always stay in the value cell of the selected row
330 if (real_column == 2 && isSelected) {
331 table.editCellAt(row, column);
332 if (table.isEditing()) {
333 table.getEditorComponent().requestFocus();
334 }
335 }
336
337 // Set up the component
338 component.setOpaque(true);
339
340 // Foreground
341 if (metadata_value_table_model.isCommon(row)) {
342 component.setForeground(Color.black);
343 }
344 else {
345 component.setForeground(Color.gray);
346 }
347
348 // Background
349 if (isSelected) {
350 component.setBackground(Configuration.getColor("coloring.workspace_heading_background", true));
351 }
352 else {
353 if (real_column < 2) {
354 component.setBackground(Configuration.getColor("coloring.collection_heading_background", true));
355 }
356 else {
357 component.setBackground(Configuration.getColor("coloring.collection_tree_background", true));
358 }
359 }
360
361 // The value column of cells never paints focus
362 if (real_column == 2) {
363 component.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
364 }
365
366 // We set a tooltip over the element column containing the definition of the element
367 if (value instanceof MetadataElement) {
368 String interface_language_code = Configuration.getLanguage();
369 String metadata_element_definition = MetadataTools.getMetadataElementAttribute((MetadataElement) value, "definition", interface_language_code, "en");
370 if (metadata_element_definition != null) {
371 component.setToolTipText(Utility.formatHTMLWidth(metadata_element_definition, 60));
372 }
373 }
374
375 return component;
376 }
377 }
378
379
380 private class MetadataValueTableKeyListener
381 extends KeyAdapter
382 {
383 /** Gives notification of key events on the text field */
384 public void keyPressed(KeyEvent key_event)
385 {
386 // Enter: save the current value then add a blank row for the selected metadata element
387 if (key_event.getKeyCode() == KeyEvent.VK_ENTER) {
388 // ...but not for extracted metadata elements of course
389 MetadataValueTableEntry metadata_value_table_entry = getSelectedMetadataValueTableEntry();
390 if (!metadata_value_table_entry.getMetadataElement().isExtractedMetadataElement()) {
391 addBlankRowForSelectedMetadataElement();
392 }
393
394 // We do not want this event to be processed by the table also
395 key_event.consume();
396 }
397 }
398 }
399
400
401 private class MetadataValueTextFieldMouseListener
402 extends MouseAdapter
403 {
404 public void mouseClicked(MouseEvent mouse_event)
405 {
406 // Double-click: pop up an editor dialog for large metadata values
407 if (mouse_event.getClickCount() == 2) {
408 EditorDialog editor_dialog = new EditorDialog();
409 String new_metadata_value_string = editor_dialog.display(metadata_value_text_field.getText());
410 if (new_metadata_value_string != null) {
411 setMetadataValueTextFieldValue(new_metadata_value_string);
412 }
413 }
414 }
415 }
416 }
417}
Note: See TracBrowser for help on using the repository browser.