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

Last change on this file since 10396 was 10011, checked in by mdewsnip, 19 years ago

Moved Utility.getImage into JarTools, as part of tidying up the Utility class.

  • Property svn:keywords set to Author Date Id Revision
File size: 15.2 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
203 // We need to listen for key presses so we can catch Enter presses
204 addKeyListener(new MetadataValueTableKeyListener());
205
206 // We need to listen for metadata changes so we can rebuild the table
207 MetadataXMLFileManager.addMetadataChangedListener(this);
208
209 // 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
210 JTableHeader table_header = getTableHeader();
211 Dimension table_header_preferred_size = table_header.getPreferredSize();
212 if (table_header_preferred_size.height < MINIMUM_TABLE_HEADER_SIZE) {
213 table_header_preferred_size.setSize(table_header_preferred_size.width, MINIMUM_TABLE_HEADER_SIZE);
214 table_header.setPreferredSize(table_header_preferred_size);
215 }
216
217 // Set the size of the table columns: 2/7 for element, 5/7 for value (actual numbers don't matter)
218 TableColumnModel column_model = getColumnModel();
219 TableColumn inherited_column = column_model.getColumn(0);
220 inherited_column.setMinWidth(25);
221 inherited_column.setPreferredWidth(25);
222 inherited_column.setMaxWidth(25);
223 TableColumn element_column = column_model.getColumn(1);
224 element_column.setPreferredWidth(200);
225 TableColumn value_column = column_model.getColumn(2);
226 value_column.setPreferredWidth(500);
227
228 // Use our own renderer for the table cells
229 MetadataValueTableCellRenderer metadata_value_table_cell_renderer = new MetadataValueTableCellRenderer();
230 inherited_column.setCellRenderer(metadata_value_table_cell_renderer);
231 element_column.setCellRenderer(metadata_value_table_cell_renderer);
232 value_column.setCellRenderer(metadata_value_table_cell_renderer);
233 }
234
235
236 private void addBlankRowForSelectedMetadataElement()
237 {
238 // Add a blank entry for the selected metadata element, then switch to it
239 MetadataElement selected_metadata_element = getSelectedMetadataValueTableEntry().getMetadataElement();
240 int blank_row = metadata_value_table_model.addBlankRowForMetadataElement(selected_metadata_element);
241 changeSelection(blank_row, 2, false, false);
242 }
243
244
245 private JTextField getMetadataValueTextField()
246 {
247 return metadata_value_text_field;
248 }
249
250
251 private MetadataValueTableEntry getSelectedMetadataValueTableEntry()
252 {
253 return metadata_value_table_model.getMetadataValueTableEntry(getSelectedRow());
254 }
255
256
257 private boolean isMouseEventForInheritedMetadataValueTableColumn(MouseEvent mouse_event)
258 {
259 return (columnAtPoint(mouse_event.getPoint()) == 0);
260 }
261
262
263 public void metadataChanged(CollectionTreeNode[] file_nodes)
264 {
265 rebuild(file_nodes);
266 }
267
268
269 private void rebuild(CollectionTreeNode[] file_nodes)
270 {
271 // Note the metadata value table entry currently selected
272 MetadataValueTableEntry selected_metadata_value_table_entry = getSelectedMetadataValueTableEntry();
273
274 // We don't want a lot of ListSelectionEvents while the table is rebuilding
275 clearSelection();
276
277 // Rebuild the metadata value table model
278 metadata_value_table_model.rebuild(file_nodes);
279
280 // Restore the metadata value table entry selection
281 if (selected_metadata_value_table_entry != null) {
282 int row_to_select = metadata_value_table_model.findMetadataValueTableEntryToSelect(selected_metadata_value_table_entry);
283 changeSelection(row_to_select, 2, false, false);
284 }
285 }
286
287
288 private void setMetadataValueTextFieldValue(String metadata_value_string)
289 {
290 metadata_value_text_field.setText(metadata_value_string);
291 metadata_value_text_field.requestFocus();
292 }
293
294
295 private void stopEditing()
296 {
297 // Save the current value in the text field, then remove the editor so it doesn't get saved again
298 TableCellEditor table_cell_editor = getCellEditor();
299 if (table_cell_editor != null) {
300 Object new_metadata_value = table_cell_editor.getCellEditorValue();
301 setValueAt(new_metadata_value, editingRow, editingColumn);
302 removeEditor();
303 }
304 }
305
306
307 private class MetadataValueTableCellRenderer
308 extends DefaultTableCellRenderer
309 {
310 /** Returns the default table cell renderer.
311 * @param table The <strong>JTable</strong>.
312 * @param value The value to assign to the cell at [row, column] as an <strong>Object</strong>.
313 * @param isSelected <i>true</i> if cell is selected.
314 * @param hasFocus <i>true</i> if cell has focus.
315 * @param row The row of the cell to render as an <i>int</i>.
316 * @param column The column of the cell to render as an <i>int</i>.
317 * @return The default table cell renderer <strong>Component</strong>.
318 */
319 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
320 {
321 JComponent component = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
322
323 // First column: inherited metadata icon
324 if (column == 0 && value != null) {
325 component = new JLabel(JarTools.getImage("upfolder.gif"));
326 }
327
328 // Make sure the focus always stay in the value cell of the selected row
329 if (column == 2 && isSelected) {
330 table.editCellAt(row, column);
331 if (table.isEditing()) {
332 table.getEditorComponent().requestFocus();
333 }
334 }
335
336 // Set up the component
337 component.setOpaque(true);
338
339 // Foreground
340 if (metadata_value_table_model.isCommon(row)) {
341 component.setForeground(Color.black);
342 }
343 else {
344 component.setForeground(Color.gray);
345 }
346
347 // Background
348 if (isSelected) {
349 component.setBackground(Configuration.getColor("coloring.workspace_heading_background", true));
350 }
351 else {
352 if (column < 2) {
353 component.setBackground(Configuration.getColor("coloring.collection_heading_background", true));
354 }
355 else {
356 component.setBackground(Configuration.getColor("coloring.collection_tree_background", true));
357 }
358 }
359
360 // The value column of cells never paints focus
361 if (column == 2) {
362 component.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
363 }
364
365 // We set a tooltip over the element column containing the definition of the element
366 if (value instanceof MetadataElement) {
367 String interface_language_code = Configuration.getLanguage();
368 String metadata_element_definition = MetadataTools.getMetadataElementAttribute((MetadataElement) value, "definition", interface_language_code, "en");
369 if (metadata_element_definition != null) {
370 component.setToolTipText(Utility.formatHTMLWidth(metadata_element_definition, 60));
371 }
372 }
373
374 return component;
375 }
376 }
377
378
379 private class MetadataValueTableKeyListener
380 extends KeyAdapter
381 {
382 /** Gives notification of key events on the text field */
383 public void keyPressed(KeyEvent key_event)
384 {
385 // Enter: save the current value then add a blank row for the selected metadata element
386 if (key_event.getKeyCode() == KeyEvent.VK_ENTER) {
387 // ...but not for extracted metadata elements of course
388 MetadataValueTableEntry metadata_value_table_entry = getSelectedMetadataValueTableEntry();
389 if (!metadata_value_table_entry.getMetadataElement().isExtractedMetadataElement()) {
390 addBlankRowForSelectedMetadataElement();
391 }
392
393 // We do not want this event to be processed by the table also
394 key_event.consume();
395 }
396 }
397 }
398
399
400 private class MetadataValueTextFieldMouseListener
401 extends MouseAdapter
402 {
403 public void mouseClicked(MouseEvent mouse_event)
404 {
405 // Double-click: pop up an editor dialog for large metadata values
406 if (mouse_event.getClickCount() == 2) {
407 EditorDialog editor_dialog = new EditorDialog();
408 String new_metadata_value_string = editor_dialog.display(metadata_value_text_field.getText());
409 if (new_metadata_value_string != null) {
410 setMetadataValueTextFieldValue(new_metadata_value_string);
411 }
412 }
413 }
414 }
415 }
416}
Note: See TracBrowser for help on using the repository browser.