source: gli/branches/rtl-gli/src/org/greenstone/gatherer/gui/MetadataValueTablePane.java@ 18297

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

interface updated to display right to left for rtl languages. This code is thanks to Amin Hejazi. It seems to be only partially complete. Amin was working with Greenstone 3 so might have missed some panels

  • 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.