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

Last change on this file since 13801 was 13801, checked in by mdewsnip, 17 years ago

No longer updates the metadata value table when selections are made in the Gather pane.

  • Property svn:keywords set to Author Date Id Revision
File size: 14.9 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 /** Called whenever the collection tree selection changes. This causes the metadata value table to be rebuilt. */
262 public void valueChanged(TreeSelectionEvent event)
263 {
264 // If we haven't got focus then it must have been a selection in the Gather pane, so don't bother rebuilding
265 if (has_focus == false) {
266 return;
267 }
268
269 // Nothing selected in the collection tree
270 if (collection_tree.getSelectionCount() == 0) {
271 file_nodes = null;
272 }
273
274 // Some files selected in the collection tree
275 else {
276 TreePath paths[] = collection_tree.getSelectionPaths();
277 file_nodes = new CollectionTreeNode[paths.length];
278 for (int i = 0; i < paths.length; i++) {
279 file_nodes[i] = (CollectionTreeNode) paths[i].getLastPathComponent();
280 }
281 }
282
283 // Update the metadata value table (and consequently, the metadata value tree)
284 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
285 }
286
287
288 private class MetadataValueTableListSelectionListener
289 implements ListSelectionListener
290 {
291 public void valueChanged(ListSelectionEvent list_selection_event)
292 {
293 // We only want to handle one event per selection, so wait for the value to stabilise
294 if (list_selection_event.getValueIsAdjusting()) {
295 return;
296 }
297
298 // Update the metadata value tree for the current table selection
299 metadata_value_tree_pane.rebuild(metadata_value_table_pane.getSelectedMetadataValueTableEntry());
300 }
301 }
302
303
304 private class MetadataValueTableMouseListener
305 extends MouseAdapter
306 {
307 public void mouseClicked(MouseEvent mouse_event)
308 {
309 // We're only interested in clicks on the inherited column
310 if (metadata_value_table_pane.isMouseEventForInheritedMetadataValueTableColumn(mouse_event) == false) {
311 return;
312 }
313
314 // If the selected metadata is inherited, switch to the folder it came from
315 MetadataValueTableEntry selected_metadata_value_table_entry = metadata_value_table_pane.getSelectedMetadataValueTableEntry();
316 if (selected_metadata_value_table_entry.isInheritedMetadata()) {
317 collection_tree.setSelection(selected_metadata_value_table_entry.getFolderMetadataInheritedFrom());
318 }
319 }
320 }
321
322
323 private class MetadataValueTextFieldDocumentListener
324 implements DocumentListener
325 {
326 /** Gives notification that an attribute or set of attributes changed */
327 public void changedUpdate(DocumentEvent document_event) {
328 validate(document_event);
329 }
330
331 /** Gives notification that there was an insert into the document */
332 public void insertUpdate(DocumentEvent document_event) {
333 validate(document_event);
334 }
335
336 /** Gives notification that a portion of the document has been removed */
337 public void removeUpdate(DocumentEvent document_event) {
338 validate(document_event);
339 }
340
341
342 /** Ensures that the value tree is updated in response to changes in the value text field */
343 private void validate(DocumentEvent document_event)
344 {
345 try {
346 Document document = document_event.getDocument();
347 String metadata_value_string = document.getText(0, document.getLength());
348 metadata_value_tree_pane.selectBestPathForMetadataValue(metadata_value_string);
349 }
350 catch (Exception exception) {
351 DebugStream.printStackTrace(exception);
352 }
353 }
354 }
355
356
357 private class MetadataValueTextFieldKeyListener
358 extends KeyAdapter
359 {
360 /** Gives notification of key events on the text field */
361 public void keyPressed(KeyEvent key_event)
362 {
363 // Tab: Auto-complete what is selected in the metadata value tree
364 if (key_event.getKeyCode() == KeyEvent.VK_TAB) {
365 MetadataValueTreeNode selected_metadata_value_tree_node = metadata_value_tree_pane.getSelectedMetadataValueTreeNode();
366 if (selected_metadata_value_tree_node != null) {
367 metadata_value_table_pane.setMetadataValueTextFieldValue(selected_metadata_value_tree_node.getFullValue());
368 }
369
370 // We do not want this event to be processed by the table also
371 key_event.consume();
372 }
373
374 // Enter: save the current value then add a blank row for the selected metadata element
375 if (key_event.getKeyCode() == KeyEvent.VK_ENTER) {
376 metadata_value_table_pane.stopEditingAndAddBlankRowForSelectedMetadataElement();
377 }
378 }
379 }
380
381
382 private class MetadataValueTreeSelectionListener
383 implements TreeSelectionListener
384 {
385 public void valueChanged(TreeSelectionEvent tree_selection_event)
386 {
387 // When a node is selected in the tree, fill the metadata value text field with the selected node's value
388 MetadataValueTreeNode selected_metadata_value_tree_node = metadata_value_tree_pane.getSelectedMetadataValueTreeNode();
389 if (selected_metadata_value_tree_node != null) {
390 metadata_value_table_pane.setMetadataValueTextFieldValue(selected_metadata_value_tree_node.getFullValue());
391 }
392 }
393 }
394}
Note: See TracBrowser for help on using the repository browser.