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

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

GLI three modes change: file tree filters are now editable in librarian mode, and regex plugin/classifier arguments are now shown in librarian mode

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