source: main/trunk/gli/src/org/greenstone/gatherer/gui/EnrichPane.java@ 29011

Last change on this file since 29011 was 23433, checked in by ak19, 14 years ago

GLI now has a gs.FilenameEncoding metadata field which appears like all the others in GLI's EnrichPane, but is unique in that this metadata (once set, changed or removed) must be applied to the affected filenames in the Collection Tree. More importantly, the changes made for this are to allow GLI's java code to interact with the recent changes to Perl where strings were made unicode-aware (for proper regex matching) but which required other changes elsewhere. To still support filenames with different encodings Perl used URL encoded versions of filenames representing characters' code point values in URL encoding. This required that GLI write out URL encoded filenames to the metadata.xml files that are associated with each folder level of a collection, so that Perl can read them. In this way, they can both speak of the same filenames. Only works on unicode 16 (such as latin-1), non-UTF8 systems. The latter is a requirement since Java uses the filesystem encoding from startup. If it is UTF8, non-recognised characters are replaced by the invalid char for UTF8. This process being destructive, we can't get the original filenames' bytecodes back. The changes made to GLI will work on Windows which is UTF-16 (windows codepage 1252), presumably also Macs (some kind of UTF-16) and also works on Native Latin 1 Linux systems. UTF-8 Linux systems need to be reconfigured to Native Latin-1, or if not installed, an administrator can install it easily.

  • Property svn:keywords set to Author Date Id Revision
File size: 16.9 KB
RevLine 
[6840]1/**
[9856]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
[6840]5 * University of Waikato, New Zealand.
6 *
[9856]7 * Author: Michael Dewsnip, NZDL Project, University of Waikato, NZ
8 * Based on code by John Thompson
[6840]9 *
[9856]10 * Copyright (C) 2005 New Zealand Digital Library Project
[6840]11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
[9856]25 *############################################################################
[6840]26 */
[9856]27
[6840]28package org.greenstone.gatherer.gui;
29
[8313]30
[6840]31import java.awt.*;
32import java.awt.event.*;
33import java.io.*;
34import java.util.*;
35import javax.swing.*;
36import javax.swing.event.*;
[9856]37import javax.swing.text.*;
[6840]38import javax.swing.tree.*;
39import org.greenstone.gatherer.Configuration;
[8236]40import org.greenstone.gatherer.DebugStream;
[6840]41import org.greenstone.gatherer.Dictionary;
42import org.greenstone.gatherer.Gatherer;
[8846]43import org.greenstone.gatherer.collection.CollectionTree;
[8783]44import org.greenstone.gatherer.collection.CollectionTreeNode;
[6840]45import org.greenstone.gatherer.gui.tree.DragTree;
[23433]46import org.greenstone.gatherer.metadata.FilenameEncoding;
[8313]47import org.greenstone.gatherer.metadata.MetadataElement;
48import org.greenstone.gatherer.metadata.MetadataValue;
49import org.greenstone.gatherer.metadata.MetadataValueTableEntry;
50import org.greenstone.gatherer.metadata.MetadataValueTreeNode;
[10547]51import org.greenstone.gatherer.metadata.MetadataXMLFileManager;
[8313]52
53
[8695]54/** Provides a view of controls for the editing of metadata.
[8313]55 */
[6840]56public class EnrichPane
57 extends JPanel
[9856]58 implements TreeSelectionListener
[8802]59{
[6840]60 static private Dimension MINIMUM_SIZE = new Dimension(100, 100);
[9856]61 static private Dimension COLLECTION_TREE_SIZE = new Dimension(250, 500);
[6840]62
[13801]63 private boolean has_focus = false;
[9856]64 /** The collection tree. */
65 private CollectionTree collection_tree = null;
[8313]66 /** The currently reported selection. */
[8783]67 private CollectionTreeNode[] file_nodes = null;
[11622]68 /** Used to dynamically filter the collection tree. */
[9856]69 private Filter collection_filter = null;
[6840]70 /** The label at the top of the collection tree, which shows the collection name. */
71 private JLabel collection_label;
[11626]72 /** The panel that contains the collection tree. */
73 private JPanel collection_pane = null;
74 /** The scrollable area into which the collection tree is placed. */
75 private JScrollPane collection_scroll = null;
[9856]76 /** The splitpane dividing the collection tree and the metadata editing controls. */
[6840]77 private JSplitPane external_split;
[9856]78 /** The metadata value table shows the metadata values that are currently assigned to a file. */
79 private MetadataValueTablePane metadata_value_table_pane = null;
80 /** The metadata value tree shows the metadata values that are currently assigned to a metadata element. */
81 private MetadataValueTreePane metadata_value_tree_pane = null;
[6840]82
[8313]83
[11629]84 public EnrichPane()
[6840]85 {
[18370]86 this.setComponentOrientation(Dictionary.getOrientation());
87 // Create the metadata value tree pane
88 metadata_value_tree_pane = new MetadataValueTreePane();
[9856]89 metadata_value_tree_pane.addMetadataValueTreeSelectionListener(new MetadataValueTreeSelectionListener());
[6840]90
[9856]91 // Create metadata value table pane
[18370]92 metadata_value_table_pane = new MetadataValueTablePane();
[9856]93 metadata_value_table_pane.addMetadataValueTableListSelectionListener(new MetadataValueTableListSelectionListener());
94 metadata_value_table_pane.addMetadataValueTableMouseListener(new MetadataValueTableMouseListener());
95 metadata_value_table_pane.addMetadataValueTextFieldDocumentListener(new MetadataValueTextFieldDocumentListener());
96 metadata_value_table_pane.addMetadataValueTextFieldKeyListener(new MetadataValueTextFieldKeyListener());
[6840]97 }
98
99
100 /** Some actions can only occur after this panel has been displayed on-screen, so this method is provided to do exactly that. Such actions include the proportioning of the split panes and the setting of table column widths.
101 */
[8313]102 public void afterDisplay()
103 {
[18370]104 if (Dictionary.getOrientation().isLeftToRight()){
105 external_split.setDividerLocation(0.3);
106 }else{
107 external_split.setDividerLocation(0.7);
108 }
[6840]109 }
[8313]110
111
[6840]112 /** Used to create, connect and layout the components to be shown on this control panel.
113 * @see org.greenstone.gatherer.Gatherer
114 * @see org.greenstone.gatherer.file.FileOpenActionListener
115 * @see org.greenstone.gatherer.gui.Filter
116 */
[8313]117 public void display()
118 {
[12145]119 JPanel left_hand_pane = new JPanel(new BorderLayout());
[18370]120 left_hand_pane.setComponentOrientation(Dictionary.getOrientation());
[12145]121 GLIButton metadata_set_button = new GLIButton(Dictionary.get("EnrichPane.ManageMetadataSets"), Dictionary.get("EnrichPane.ManageMetadataSets_Tooltip"));
122 metadata_set_button.addActionListener(new ActionListener() {
123 public void actionPerformed(ActionEvent event) {
124 MetadataSetDialog msd = new MetadataSetDialog();
125 if (msd.setsChanged()) {
126 valueChanged(null);
127 }
128 }
129 });
130
[11761]131 // Collection Tree
[11626]132 collection_pane = new JPanel(new BorderLayout());
[18370]133 // collection_pane.setComponentOrientation(Dictionary.getOrientation());
[6840]134 collection_pane.setMinimumSize(MINIMUM_SIZE);
[9856]135 collection_pane.setPreferredSize(COLLECTION_TREE_SIZE);
[6840]136
[12119]137 collection_label = new JLabel(Dictionary.get("Collection.No_Collection"));
[18370]138 collection_label.setComponentOrientation(Dictionary.getOrientation());
[6840]139 collection_label.setOpaque(true);
140
[11627]141 collection_tree = Gatherer.c_man.getCollectionTree();
[6840]142 collection_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
[18370]143 collection_tree.addTreeSelectionListener(this);
144 collection_tree.setComponentOrientation(Dictionary.getOrientation());
[11619]145 collection_filter = collection_tree.getFilter();
[11761]146 external_split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
[18370]147 external_split.setComponentOrientation(Dictionary.getOrientation());
[6840]148 // Layout
149 collection_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(3,3,3,3), BorderFactory.createLoweredBevelBorder()));
150 collection_pane.setMinimumSize(MINIMUM_SIZE);
151 collection_pane.setPreferredSize(new Dimension(Gatherer.g_man.getSize().width / 3, Gatherer.g_man.getSize().height));
[18370]152 collection_pane.setComponentOrientation(Dictionary.getOrientation());
[6840]153 // Collection Pane
154 collection_pane.add(collection_label, BorderLayout.NORTH);
155
[9856]156 JSplitPane metadata_editing_pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
157 metadata_editing_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
158 metadata_editing_pane.setDividerSize(8);
[18370]159 metadata_editing_pane.setComponentOrientation(Dictionary.getOrientation());
160
[9856]161 metadata_editing_pane.add(metadata_value_table_pane, JSplitPane.TOP);
162 metadata_editing_pane.add(metadata_value_tree_pane, JSplitPane.BOTTOM);
163 metadata_editing_pane.setDividerLocation(250);
[6840]164
[12145]165 left_hand_pane.add(collection_pane, BorderLayout.CENTER);
166 left_hand_pane.add(metadata_set_button, BorderLayout.SOUTH);
[18370]167 if (Dictionary.getOrientation().isLeftToRight()){
168 external_split.add(left_hand_pane, JSplitPane.LEFT);
169 external_split.add(metadata_editing_pane, JSplitPane.RIGHT);
170 }else{
171 external_split.add(left_hand_pane, JSplitPane.RIGHT);
172 external_split.add(metadata_editing_pane, JSplitPane.LEFT);
173 }
[6840]174
[12145]175
176
[6840]177 this.setLayout(new BorderLayout());
178 this.add(external_split, BorderLayout.CENTER);
179 }
180
181
[9856]182 /** Called to inform this pane that it has just gained focus as an effect of the user clicking on its tab
[6840]183 */
[8313]184 public void gainFocus()
185 {
[13801]186 // Remember that we currently have focus
187 has_focus = true;
188
[11626]189 // Add the collection tree and filter back into this pane
190 collection_scroll = new JScrollPane(collection_tree);
191 collection_pane.add(collection_scroll, BorderLayout.CENTER);
192 collection_pane.add(collection_filter, BorderLayout.SOUTH);
193
[8313]194 // Select the first node in the tree if nothing is already selected
[11825]195 if (collection_tree.getSelectionPaths() == null && collection_tree.getRowCount() > 0) {
[8313]196 collection_tree.setImmediate(true);
197 collection_tree.setSelectionRow(0);
198 collection_tree.setImmediate(false);
[8359]199 return;
[6840]200 }
201
[8313]202 // Force all of the controls to be updated
[9856]203 valueChanged(null);
[6840]204 }
205
206
[10387]207 /** Called to inform this pane that it has just lost focus as an effect of the user clicking on another tab
208 */
209 public void loseFocus()
210 {
[10604]211 // Very important: make sure metadata value is saved before leaving the pane
212 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
213
[13705]214 // Make sure all the metadata has been saved to file
215 MetadataXMLFileManager.saveMetadataXMLFiles();
[11626]216
217 // Remove the collection tree and filter from this pane so it can be added to the Gather pane
218 collection_pane.remove(collection_scroll);
219 collection_pane.remove(collection_filter);
[13801]220
221 // Remember that we no longer have focus
222 has_focus = false;
[10387]223 }
224
225
[6840]226 /** Called whenever the detail mode changes to ensure the filters are at an appropriate level (ie only editable by those that understand regular expression matching)
227 * @param mode the mode level as an int
228 */
[8313]229 public void modeChanged(int mode)
230 {
[18593]231 collection_filter.setEditable(mode >= Configuration.LIBRARIAN_MODE);
[6840]232 }
233
234
[8813]235 /** Refresh this pane, depending on what has just happened (refresh_reason). */
236 public void refresh(int refresh_reason, boolean collection_loaded)
[8353]237 {
[8813]238 if (collection_loaded) {
239 // Update collection label
[12119]240 collection_label.setText(Dictionary.get("Collection.Collection"));
[8353]241 collection_label.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
242 collection_label.setForeground(Configuration.getColor("coloring.collection_heading_foreground", false));
243
[8813]244 // Update collection tree
245 if (refresh_reason == Gatherer.COLLECTION_OPENED) {
[8846]246 collection_tree.setModel(Gatherer.c_man.getCollectionTreeModel());
[8354]247 }
[8813]248
249 // Update collection filter
250 collection_filter.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
[8353]251 }
252 else {
[8813]253 // Update collection label
[12119]254 collection_label.setText(Dictionary.get("Collection.No_Collection"));
[8353]255 collection_label.setBackground(Color.lightGray);
256 collection_label.setForeground(Color.black);
[8354]257
[8813]258 // Update collection tree
259 collection_tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode("Error")));
260
261 // Update collection filter
262 collection_filter.setBackground(Color.lightGray);
[8353]263 }
264
[8813]265 // Enable or disable the controls
266 collection_tree.setEnabled(collection_loaded);
267 collection_filter.setEnabled(collection_loaded);
268
269 // Force the metadata table to be rebuilt (for switching extracted metadata on or off)
270 if (refresh_reason == Gatherer.PREFERENCES_CHANGED) {
[9856]271 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
[8813]272 }
[8353]273 }
274
275
[18199]276 /** Allows other classes to request the enrich pane to prepare for metadata
277 * saving.
278 * @author John Thompson, DL Consulting Ltd
279 */
280 public void stopEditingAndRebuild()
281 {
282 // Update the metadata value table (and consequently, the metadata value tree)
283 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
284 }
285 /** stopEditingAndRebuild() **/
286
287 /** Called whenever the collection tree selection changes. This causes the metadata value table to be rebuilt. */
288 public void valueChanged(TreeSelectionEvent event)
[8313]289 {
[23433]290 if(FilenameEncoding.isRefreshRequired()) {
291 // The CollectionTree is in the process of being re-built to deal with filename-encodings,
292 // so don't mess up the table during that time.
293 // (CollectionTreeNode.refreshDescendantEncodings() doesn't cope well if this method
294 // responds on Tree selection changes while the tree is updating its encodings, resulting in lost
295 // and misplaced metadata values in the table and thereby in the metadata.xml files themselves).
296 return;
297 }
298
299
[13801]300 // If we haven't got focus then it must have been a selection in the Gather pane, so don't bother rebuilding
301 if (has_focus == false) {
302 return;
303 }
304
[8313]305 // Nothing selected in the collection tree
306 if (collection_tree.getSelectionCount() == 0) {
307 file_nodes = null;
[6840]308 }
309
[8313]310 // Some files selected in the collection tree
[6840]311 else {
[8313]312 TreePath paths[] = collection_tree.getSelectionPaths();
[8783]313 file_nodes = new CollectionTreeNode[paths.length];
[8313]314 for (int i = 0; i < paths.length; i++) {
[8783]315 file_nodes[i] = (CollectionTreeNode) paths[i].getLastPathComponent();
[6840]316 }
317 }
[8313]318
319 // Update the metadata value table (and consequently, the metadata value tree)
[9856]320 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
[6840]321 }
322
[8313]323
[9856]324 private class MetadataValueTableListSelectionListener
325 implements ListSelectionListener
[8313]326 {
[9856]327 public void valueChanged(ListSelectionEvent list_selection_event)
[8313]328 {
[9856]329 // We only want to handle one event per selection, so wait for the value to stabilise
330 if (list_selection_event.getValueIsAdjusting()) {
331 return;
[9334]332 }
[9331]333
[9856]334 // Update the metadata value tree for the current table selection
335 metadata_value_tree_pane.rebuild(metadata_value_table_pane.getSelectedMetadataValueTableEntry());
[6840]336 }
337 }
338
339
[9856]340 private class MetadataValueTableMouseListener
341 extends MouseAdapter
[8313]342 {
[9856]343 public void mouseClicked(MouseEvent mouse_event)
[8313]344 {
[9856]345 // We're only interested in clicks on the inherited column
346 if (metadata_value_table_pane.isMouseEventForInheritedMetadataValueTableColumn(mouse_event) == false) {
347 return;
348 }
[6840]349
[9856]350 // If the selected metadata is inherited, switch to the folder it came from
351 MetadataValueTableEntry selected_metadata_value_table_entry = metadata_value_table_pane.getSelectedMetadataValueTableEntry();
352 if (selected_metadata_value_table_entry.isInheritedMetadata()) {
353 collection_tree.setSelection(selected_metadata_value_table_entry.getFolderMetadataInheritedFrom());
[9334]354 }
[8313]355 }
356 }
[6840]357
358
[9856]359 private class MetadataValueTextFieldDocumentListener
360 implements DocumentListener
[8313]361 {
[9856]362 /** Gives notification that an attribute or set of attributes changed */
363 public void changedUpdate(DocumentEvent document_event) {
364 validate(document_event);
365 }
[9331]366
[9856]367 /** Gives notification that there was an insert into the document */
368 public void insertUpdate(DocumentEvent document_event) {
369 validate(document_event);
[9331]370 }
371
[9856]372 /** Gives notification that a portion of the document has been removed */
373 public void removeUpdate(DocumentEvent document_event) {
374 validate(document_event);
375 }
376
377
378 /** Ensures that the value tree is updated in response to changes in the value text field */
379 private void validate(DocumentEvent document_event)
[8313]380 {
[9334]381 try {
[9856]382 Document document = document_event.getDocument();
383 String metadata_value_string = document.getText(0, document.getLength());
384 metadata_value_tree_pane.selectBestPathForMetadataValue(metadata_value_string);
[9334]385 }
386 catch (Exception exception) {
387 DebugStream.printStackTrace(exception);
388 }
[6840]389 }
[8313]390 }
[6840]391
[8313]392
[9856]393 private class MetadataValueTextFieldKeyListener
394 extends KeyAdapter
[8313]395 {
[9856]396 /** Gives notification of key events on the text field */
397 public void keyPressed(KeyEvent key_event)
[8313]398 {
[9856]399 // Tab: Auto-complete what is selected in the metadata value tree
400 if (key_event.getKeyCode() == KeyEvent.VK_TAB) {
401 MetadataValueTreeNode selected_metadata_value_tree_node = metadata_value_tree_pane.getSelectedMetadataValueTreeNode();
402 if (selected_metadata_value_tree_node != null) {
403 metadata_value_table_pane.setMetadataValueTextFieldValue(selected_metadata_value_tree_node.getFullValue());
[8313]404 }
[6840]405
[9856]406 // We do not want this event to be processed by the table also
407 key_event.consume();
[8313]408 }
[6840]409
[9856]410 // Enter: save the current value then add a blank row for the selected metadata element
411 if (key_event.getKeyCode() == KeyEvent.VK_ENTER) {
412 metadata_value_table_pane.stopEditingAndAddBlankRowForSelectedMetadataElement();
[8364]413 }
414 }
[7098]415 }
416
417
[9856]418 private class MetadataValueTreeSelectionListener
419 implements TreeSelectionListener
[8313]420 {
[9856]421 public void valueChanged(TreeSelectionEvent tree_selection_event)
[6840]422 {
[9856]423 // When a node is selected in the tree, fill the metadata value text field with the selected node's value
424 MetadataValueTreeNode selected_metadata_value_tree_node = metadata_value_tree_pane.getSelectedMetadataValueTreeNode();
425 if (selected_metadata_value_tree_node != null) {
426 metadata_value_table_pane.setMetadataValueTextFieldValue(selected_metadata_value_tree_node.getFullValue());
[6840]427 }
428 }
429 }
430}
Note: See TracBrowser for help on using the repository browser.