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

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

a fix provided by John from Dl Consulting. File->Save now saves the metadata in the Enrich Pane as well as the collection config file. Previously, metadata was only saved when you left the pane.

  • 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 * Based on code by John Thompson
9 *
10 * Copyright (C) 2005 New Zealand Digital Library Project
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.
25 *############################################################################
26 */
27
28package org.greenstone.gatherer.gui;
29
30
31import java.awt.*;
32import java.awt.event.*;
33import java.io.*;
34import java.util.*;
35import javax.swing.*;
36import javax.swing.event.*;
37import javax.swing.text.*;
38import javax.swing.tree.*;
39import org.greenstone.gatherer.Configuration;
40import org.greenstone.gatherer.DebugStream;
41import org.greenstone.gatherer.Dictionary;
42import org.greenstone.gatherer.Gatherer;
43import org.greenstone.gatherer.collection.CollectionTree;
44import org.greenstone.gatherer.collection.CollectionTreeNode;
45import org.greenstone.gatherer.gui.tree.DragTree;
46import org.greenstone.gatherer.metadata.MetadataElement;
47import org.greenstone.gatherer.metadata.MetadataValue;
48import org.greenstone.gatherer.metadata.MetadataValueTableEntry;
49import org.greenstone.gatherer.metadata.MetadataValueTreeNode;
50import org.greenstone.gatherer.metadata.MetadataXMLFileManager;
51
52
53/** Provides a view of controls for the editing of metadata.
54 */
55public class EnrichPane
56 extends JPanel
57 implements TreeSelectionListener
58{
59 static private Dimension MINIMUM_SIZE = new Dimension(100, 100);
60 static private Dimension COLLECTION_TREE_SIZE = new Dimension(250, 500);
61
62 private boolean has_focus = false;
63 /** The collection tree. */
64 private CollectionTree collection_tree = null;
65 /** The currently reported selection. */
66 private CollectionTreeNode[] file_nodes = null;
67 /** Used to dynamically filter the collection tree. */
68 private Filter collection_filter = null;
69 /** The label at the top of the collection tree, which shows the collection name. */
70 private JLabel collection_label;
71 /** The panel that contains the collection tree. */
72 private JPanel collection_pane = null;
73 /** The scrollable area into which the collection tree is placed. */
74 private JScrollPane collection_scroll = null;
75 /** The splitpane dividing the collection tree and the metadata editing controls. */
76 private JSplitPane external_split;
77 /** The metadata value table shows the metadata values that are currently assigned to a file. */
78 private MetadataValueTablePane metadata_value_table_pane = null;
79 /** The metadata value tree shows the metadata values that are currently assigned to a metadata element. */
80 private MetadataValueTreePane metadata_value_tree_pane = null;
81
82
83 public EnrichPane()
84 {
85 // Create the metadata value tree pane
86 metadata_value_tree_pane = new MetadataValueTreePane();
87 metadata_value_tree_pane.addMetadataValueTreeSelectionListener(new MetadataValueTreeSelectionListener());
88
89 // Create metadata value table pane
90 metadata_value_table_pane = new MetadataValueTablePane();
91 metadata_value_table_pane.addMetadataValueTableListSelectionListener(new MetadataValueTableListSelectionListener());
92 metadata_value_table_pane.addMetadataValueTableMouseListener(new MetadataValueTableMouseListener());
93 metadata_value_table_pane.addMetadataValueTextFieldDocumentListener(new MetadataValueTextFieldDocumentListener());
94 metadata_value_table_pane.addMetadataValueTextFieldKeyListener(new MetadataValueTextFieldKeyListener());
95 }
96
97
98 /** 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.
99 */
100 public void afterDisplay()
101 {
102 external_split.setDividerLocation(0.3);
103 }
104
105
106 /** Used to create, connect and layout the components to be shown on this control panel.
107 * @see org.greenstone.gatherer.Gatherer
108 * @see org.greenstone.gatherer.file.FileOpenActionListener
109 * @see org.greenstone.gatherer.gui.Filter
110 */
111 public void display()
112 {
113 JPanel left_hand_pane = new JPanel(new BorderLayout());
114 GLIButton metadata_set_button = new GLIButton(Dictionary.get("EnrichPane.ManageMetadataSets"), Dictionary.get("EnrichPane.ManageMetadataSets_Tooltip"));
115 metadata_set_button.addActionListener(new ActionListener() {
116 public void actionPerformed(ActionEvent event) {
117 MetadataSetDialog msd = new MetadataSetDialog();
118 if (msd.setsChanged()) {
119 valueChanged(null);
120 }
121 }
122 });
123
124 // Collection Tree
125 collection_pane = new JPanel(new BorderLayout());
126 collection_pane.setMinimumSize(MINIMUM_SIZE);
127 collection_pane.setPreferredSize(COLLECTION_TREE_SIZE);
128
129 collection_label = new JLabel(Dictionary.get("Collection.No_Collection"));
130 collection_label.setOpaque(true);
131
132 collection_tree = Gatherer.c_man.getCollectionTree();
133 collection_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
134 collection_tree.addTreeSelectionListener(this);
135 collection_filter = collection_tree.getFilter();
136
137 external_split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
138
139 // Layout
140 collection_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(3,3,3,3), BorderFactory.createLoweredBevelBorder()));
141 collection_pane.setMinimumSize(MINIMUM_SIZE);
142 collection_pane.setPreferredSize(new Dimension(Gatherer.g_man.getSize().width / 3, Gatherer.g_man.getSize().height));
143
144 // Collection Pane
145 collection_pane.add(collection_label, BorderLayout.NORTH);
146
147 JSplitPane metadata_editing_pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
148 metadata_editing_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
149 metadata_editing_pane.setDividerSize(8);
150
151 metadata_editing_pane.add(metadata_value_table_pane, JSplitPane.TOP);
152 metadata_editing_pane.add(metadata_value_tree_pane, JSplitPane.BOTTOM);
153 metadata_editing_pane.setDividerLocation(250);
154
155 left_hand_pane.add(collection_pane, BorderLayout.CENTER);
156 left_hand_pane.add(metadata_set_button, BorderLayout.SOUTH);
157 external_split.add(left_hand_pane, JSplitPane.LEFT);
158 external_split.add(metadata_editing_pane, JSplitPane.RIGHT);
159
160
161
162 this.setLayout(new BorderLayout());
163 this.add(external_split, BorderLayout.CENTER);
164 }
165
166
167 /** Called to inform this pane that it has just gained focus as an effect of the user clicking on its tab
168 */
169 public void gainFocus()
170 {
171 // Remember that we currently have focus
172 has_focus = true;
173
174 // Add the collection tree and filter back into this pane
175 collection_scroll = new JScrollPane(collection_tree);
176 collection_pane.add(collection_scroll, BorderLayout.CENTER);
177 collection_pane.add(collection_filter, BorderLayout.SOUTH);
178
179 // Select the first node in the tree if nothing is already selected
180 if (collection_tree.getSelectionPaths() == null && collection_tree.getRowCount() > 0) {
181 collection_tree.setImmediate(true);
182 collection_tree.setSelectionRow(0);
183 collection_tree.setImmediate(false);
184 return;
185 }
186
187 // Force all of the controls to be updated
188 valueChanged(null);
189 }
190
191
192 /** Called to inform this pane that it has just lost focus as an effect of the user clicking on another tab
193 */
194 public void loseFocus()
195 {
196 // Very important: make sure metadata value is saved before leaving the pane
197 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
198
199 // Make sure all the metadata has been saved to file
200 MetadataXMLFileManager.saveMetadataXMLFiles();
201
202 // Remove the collection tree and filter from this pane so it can be added to the Gather pane
203 collection_pane.remove(collection_scroll);
204 collection_pane.remove(collection_filter);
205
206 // Remember that we no longer have focus
207 has_focus = false;
208 }
209
210
211 /** 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)
212 * @param mode the mode level as an int
213 */
214 public void modeChanged(int mode)
215 {
216 collection_filter.setEditable(mode > Configuration.LIBRARIAN_MODE);
217 }
218
219
220 /** Refresh this pane, depending on what has just happened (refresh_reason). */
221 public void refresh(int refresh_reason, boolean collection_loaded)
222 {
223 if (collection_loaded) {
224 // Update collection label
225 collection_label.setText(Dictionary.get("Collection.Collection"));
226 collection_label.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
227 collection_label.setForeground(Configuration.getColor("coloring.collection_heading_foreground", false));
228
229 // Update collection tree
230 if (refresh_reason == Gatherer.COLLECTION_OPENED) {
231 collection_tree.setModel(Gatherer.c_man.getCollectionTreeModel());
232 }
233
234 // Update collection filter
235 collection_filter.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
236 }
237 else {
238 // Update collection label
239 collection_label.setText(Dictionary.get("Collection.No_Collection"));
240 collection_label.setBackground(Color.lightGray);
241 collection_label.setForeground(Color.black);
242
243 // Update collection tree
244 collection_tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode("Error")));
245
246 // Update collection filter
247 collection_filter.setBackground(Color.lightGray);
248 }
249
250 // Enable or disable the controls
251 collection_tree.setEnabled(collection_loaded);
252 collection_filter.setEnabled(collection_loaded);
253
254 // Force the metadata table to be rebuilt (for switching extracted metadata on or off)
255 if (refresh_reason == Gatherer.PREFERENCES_CHANGED) {
256 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
257 }
258 }
259
260
261 /** Allows other classes to request the enrich pane to prepare for metadata
262 * saving.
263 * @author John Thompson, DL Consulting Ltd
264 */
265 public void stopEditingAndRebuild()
266 {
267 // Update the metadata value table (and consequently, the metadata value tree)
268 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
269 }
270 /** stopEditingAndRebuild() **/
271
272 /** Called whenever the collection tree selection changes. This causes the metadata value table to be rebuilt. */
273 public void valueChanged(TreeSelectionEvent event)
274 {
275 // If we haven't got focus then it must have been a selection in the Gather pane, so don't bother rebuilding
276 if (has_focus == false) {
277 return;
278 }
279
280 // Nothing selected in the collection tree
281 if (collection_tree.getSelectionCount() == 0) {
282 file_nodes = null;
283 }
284
285 // Some files selected in the collection tree
286 else {
287 TreePath paths[] = collection_tree.getSelectionPaths();
288 file_nodes = new CollectionTreeNode[paths.length];
289 for (int i = 0; i < paths.length; i++) {
290 file_nodes[i] = (CollectionTreeNode) paths[i].getLastPathComponent();
291 }
292 }
293
294 // Update the metadata value table (and consequently, the metadata value tree)
295 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
296 }
297
298
299 private class MetadataValueTableListSelectionListener
300 implements ListSelectionListener
301 {
302 public void valueChanged(ListSelectionEvent list_selection_event)
303 {
304 // We only want to handle one event per selection, so wait for the value to stabilise
305 if (list_selection_event.getValueIsAdjusting()) {
306 return;
307 }
308
309 // Update the metadata value tree for the current table selection
310 metadata_value_tree_pane.rebuild(metadata_value_table_pane.getSelectedMetadataValueTableEntry());
311 }
312 }
313
314
315 private class MetadataValueTableMouseListener
316 extends MouseAdapter
317 {
318 public void mouseClicked(MouseEvent mouse_event)
319 {
320 // We're only interested in clicks on the inherited column
321 if (metadata_value_table_pane.isMouseEventForInheritedMetadataValueTableColumn(mouse_event) == false) {
322 return;
323 }
324
325 // If the selected metadata is inherited, switch to the folder it came from
326 MetadataValueTableEntry selected_metadata_value_table_entry = metadata_value_table_pane.getSelectedMetadataValueTableEntry();
327 if (selected_metadata_value_table_entry.isInheritedMetadata()) {
328 collection_tree.setSelection(selected_metadata_value_table_entry.getFolderMetadataInheritedFrom());
329 }
330 }
331 }
332
333
334 private class MetadataValueTextFieldDocumentListener
335 implements DocumentListener
336 {
337 /** Gives notification that an attribute or set of attributes changed */
338 public void changedUpdate(DocumentEvent document_event) {
339 validate(document_event);
340 }
341
342 /** Gives notification that there was an insert into the document */
343 public void insertUpdate(DocumentEvent document_event) {
344 validate(document_event);
345 }
346
347 /** Gives notification that a portion of the document has been removed */
348 public void removeUpdate(DocumentEvent document_event) {
349 validate(document_event);
350 }
351
352
353 /** Ensures that the value tree is updated in response to changes in the value text field */
354 private void validate(DocumentEvent document_event)
355 {
356 try {
357 Document document = document_event.getDocument();
358 String metadata_value_string = document.getText(0, document.getLength());
359 metadata_value_tree_pane.selectBestPathForMetadataValue(metadata_value_string);
360 }
361 catch (Exception exception) {
362 DebugStream.printStackTrace(exception);
363 }
364 }
365 }
366
367
368 private class MetadataValueTextFieldKeyListener
369 extends KeyAdapter
370 {
371 /** Gives notification of key events on the text field */
372 public void keyPressed(KeyEvent key_event)
373 {
374 // Tab: Auto-complete what is selected in the metadata value tree
375 if (key_event.getKeyCode() == KeyEvent.VK_TAB) {
376 MetadataValueTreeNode selected_metadata_value_tree_node = metadata_value_tree_pane.getSelectedMetadataValueTreeNode();
377 if (selected_metadata_value_tree_node != null) {
378 metadata_value_table_pane.setMetadataValueTextFieldValue(selected_metadata_value_tree_node.getFullValue());
379 }
380
381 // We do not want this event to be processed by the table also
382 key_event.consume();
383 }
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 metadata_value_table_pane.stopEditingAndAddBlankRowForSelectedMetadataElement();
388 }
389 }
390 }
391
392
393 private class MetadataValueTreeSelectionListener
394 implements TreeSelectionListener
395 {
396 public void valueChanged(TreeSelectionEvent tree_selection_event)
397 {
398 // When a node is selected in the tree, fill the metadata value text field with the selected node's value
399 MetadataValueTreeNode selected_metadata_value_tree_node = metadata_value_tree_pane.getSelectedMetadataValueTreeNode();
400 if (selected_metadata_value_tree_node != null) {
401 metadata_value_table_pane.setMetadataValueTextFieldValue(selected_metadata_value_tree_node.getFullValue());
402 }
403 }
404 }
405}
Note: See TracBrowser for help on using the repository browser.