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

Last change on this file since 12145 was 12145, checked in by kjdon, 18 years ago

added a manage metadata sets button underneath the collection tree

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