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

Last change on this file since 18376 was 18370, checked in by kjdon, 15 years ago

committed code submitted by Amin Hedjazi for making the GLI right to left. I worked on this code on the rtl-gli branch, then merged the branch back to the trunk at revision 18368. The branch code was slightly different in a couple of places where it shouldn't have been. So don't use the branch code next time. Start a new branch.

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