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

Last change on this file since 11905 was 11825, checked in by mdewsnip, 18 years ago

Fixed a bug where the collection tree would stuff up between Gather and Enrich panes if the collection was empty.

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