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

Last change on this file since 10604 was 10604, checked in by mdewsnip, 19 years ago

Fixed a nasty bug discovered at the 2005 Fiji workshop: if you enter a metadata value in the Enrich pane and then leave the pane before the value is saved (ie. pressing Enter, or Up or Down, or choosing another file or metadata element), all the metadata in the folder is lost.

  • Property svn:keywords set to Author Date Id Revision
File size: 24.0 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;
51import org.greenstone.gatherer.util.DragGroup;
52import org.greenstone.gatherer.util.TreeSynchronizer;
53
54
55/** Provides a view of controls for the editing of metadata.
56 */
57public class EnrichPane
58 extends JPanel
59 implements TreeSelectionListener
60{
61 static private Dimension MINIMUM_SIZE = new Dimension(100, 100);
62 static private Dimension COLLECTION_TREE_SIZE = new Dimension(250, 500);
63
64 /** The collection tree. */
65 private CollectionTree collection_tree = null;
66 /** The currently reported selection. */
67 private CollectionTreeNode[] file_nodes = null;
68 /** Used to dynamically filter the collection tree. Synchronized with the same filter in the Gather view. */
69 private Filter collection_filter = null;
70 /** The label at the top of the collection tree, which shows the collection name. */
71 private JLabel collection_label;
72 /** The splitpane dividing the collection tree and the metadata editing controls. */
73 private JSplitPane external_split;
74 /** The metadata value table shows the metadata values that are currently assigned to a file. */
75 private MetadataValueTablePane metadata_value_table_pane = null;
76 /** The metadata value tree shows the metadata values that are currently assigned to a metadata element. */
77 private MetadataValueTreePane metadata_value_tree_pane = null;
78 /** Provide synchronization between the collection trees in this view and the collection pane view. */
79 private TreeSynchronizer collection_tree_sync = null;
80
81
82 /** Constructor.
83 * @param tree_sync The <strong>TreeSynchronizer</strong> to be used on the collection tree
84 */
85 public EnrichPane(TreeSynchronizer collection_tree_sync)
86 {
87 this.collection_tree_sync = collection_tree_sync;
88
89 // Create the metadata value tree pane
90 metadata_value_tree_pane = new MetadataValueTreePane();
91 metadata_value_tree_pane.addMetadataValueTreeSelectionListener(new MetadataValueTreeSelectionListener());
92
93 // Create metadata value table pane
94 metadata_value_table_pane = new MetadataValueTablePane();
95 metadata_value_table_pane.addMetadataValueTableListSelectionListener(new MetadataValueTableListSelectionListener());
96 metadata_value_table_pane.addMetadataValueTableMouseListener(new MetadataValueTableMouseListener());
97 metadata_value_table_pane.addMetadataValueTextFieldDocumentListener(new MetadataValueTextFieldDocumentListener());
98 metadata_value_table_pane.addMetadataValueTextFieldKeyListener(new MetadataValueTextFieldKeyListener());
99 }
100
101
102 /** 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.
103 */
104 public void afterDisplay()
105 {
106 external_split.setDividerLocation(0.3);
107 }
108
109
110 /** Used to create, connect and layout the components to be shown on this control panel.
111 * @see org.greenstone.gatherer.Gatherer
112 * @see org.greenstone.gatherer.file.FileOpenActionListener
113 * @see org.greenstone.gatherer.gui.Filter
114 */
115 public void display()
116 {
117 // Creation
118 JPanel collection_pane = new JPanel(new BorderLayout());
119 collection_pane.setMinimumSize(MINIMUM_SIZE);
120 collection_pane.setPreferredSize(COLLECTION_TREE_SIZE);
121
122 external_split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
123
124 collection_label = new JLabel();
125 Dictionary.registerText(collection_label, "Collection.No_Collection");
126 collection_label.setOpaque(true);
127
128 DragGroup group = new DragGroup();
129 collection_tree = new CollectionTree("Enrich", Gatherer.c_man.getCollectionTreeModel(), false);
130 group.add(collection_tree);
131 collection_tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
132 collection_tree.putClientProperty("JTree.lineStyle", "Angled");
133 collection_tree.addMouseListener(Gatherer.g_man.foa_listener);
134 collection_tree.addMouseListener(new RightButtonListener());
135 collection_tree.addTreeSelectionListener(this);
136 collection_tree.addTreeExpansionListener(Gatherer.g_man.foa_listener);
137 collection_tree.setBackgroundNonSelectionColor(Configuration.getColor("coloring.collection_tree_background", false));
138 collection_tree.setTextNonSelectionColor(Configuration.getColor("coloring.collection_tree_foreground", false));
139 collection_tree.setBackgroundSelectionColor(Configuration.getColor("coloring.collection_selection_background", false));
140 collection_tree.setTextSelectionColor(Configuration.getColor("coloring.collection_selection_foreground", false));
141 collection_tree.setRootVisible(false);
142
143 KeyListenerImpl key_listener = new KeyListenerImpl();
144 collection_tree.addKeyListener(key_listener);
145 JScrollPane collection_scroll = new JScrollPane(collection_tree);
146
147 collection_filter = Gatherer.g_man.getFilter(collection_tree);
148 collection_filter.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
149 collection_filter.setEditable(Configuration.getMode() > Configuration.LIBRARIAN_MODE);
150 Dictionary.registerTooltip(collection_filter.getComboBox(), "Collection.Filter_Tooltip");
151
152 // Layout
153 collection_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(3,3,3,3), BorderFactory.createLoweredBevelBorder()));
154 collection_pane.setMinimumSize(MINIMUM_SIZE);
155 collection_pane.setPreferredSize(new Dimension(Gatherer.g_man.getSize().width / 3, Gatherer.g_man.getSize().height));
156
157 // Collection Pane
158 collection_pane.add(collection_label, BorderLayout.NORTH);
159 collection_pane.add(collection_scroll, BorderLayout.CENTER);
160 collection_pane.add(collection_filter, BorderLayout.SOUTH);
161
162 JSplitPane metadata_editing_pane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
163 metadata_editing_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
164 metadata_editing_pane.setDividerSize(8);
165
166 metadata_editing_pane.add(metadata_value_table_pane, JSplitPane.TOP);
167 metadata_editing_pane.add(metadata_value_tree_pane, JSplitPane.BOTTOM);
168 metadata_editing_pane.setDividerLocation(250);
169
170 external_split.add(collection_pane, JSplitPane.LEFT);
171 external_split.add(metadata_editing_pane, JSplitPane.RIGHT);
172
173 this.setLayout(new BorderLayout());
174 this.add(external_split, BorderLayout.CENTER);
175 }
176
177
178 /** Called to inform this pane that it has just gained focus as an effect of the user clicking on its tab
179 */
180 public void gainFocus()
181 {
182 // If there is nothing in the collection tree there is nothing to do
183 if (collection_tree == null || collection_tree.getRowCount() == 0) {
184 return;
185 }
186
187 // Select the first node in the tree if nothing is already selected
188 if (collection_tree.getSelectionPaths() == null) {
189 collection_tree.setImmediate(true);
190 collection_tree.setSelectionRow(0);
191 collection_tree.setImmediate(false);
192 return;
193 }
194
195 // Force all of the controls to be updated
196 valueChanged(null);
197 }
198
199
200 /** Called to inform this pane that it has just lost focus as an effect of the user clicking on another tab
201 */
202 public void loseFocus()
203 {
204 // Very important: make sure metadata value is saved before leaving the pane
205 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
206
207 // Upload the modified metadata.xml files to the server now, if we're using one
208 MetadataXMLFileManager.uploadModifiedMetadataXMLFiles();
209 }
210
211
212 /** 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)
213 * @param mode the mode level as an int
214 */
215 public void modeChanged(int mode)
216 {
217 collection_filter.setEditable(mode > Configuration.LIBRARIAN_MODE);
218 }
219
220
221 /** Refresh this pane, depending on what has just happened (refresh_reason). */
222 public void refresh(int refresh_reason, boolean collection_loaded)
223 {
224 if (collection_loaded) {
225 // Update collection label
226 Dictionary.registerText(collection_label, "Collection.Collection");
227 collection_label.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
228 collection_label.setForeground(Configuration.getColor("coloring.collection_heading_foreground", false));
229
230 // Update collection tree
231 if (refresh_reason == Gatherer.COLLECTION_OPENED) {
232 collection_tree.setModel(Gatherer.c_man.getCollectionTreeModel());
233 }
234
235 // Update collection filter
236 collection_filter.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
237 }
238 else {
239 // Update collection label
240 Dictionary.registerText(collection_label, "Collection.No_Collection");
241 collection_label.setBackground(Color.lightGray);
242 collection_label.setForeground(Color.black);
243
244 // Update collection tree
245 collection_tree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode("Error")));
246
247 // Update collection filter
248 collection_filter.setBackground(Color.lightGray);
249 }
250
251 // Enable or disable the controls
252 collection_tree.setEnabled(collection_loaded);
253 collection_filter.setEnabled(collection_loaded);
254
255 // Ensure that this collection tree view is synchronized with all others
256 collection_tree_sync.add(collection_tree);
257
258 // Force the metadata table to be rebuilt (for switching extracted metadata on or off)
259 if (refresh_reason == Gatherer.PREFERENCES_CHANGED) {
260 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
261 }
262 }
263
264
265 /** Called whenever the collection tree selection changes. This causes the metadata value table to be rebuilt. */
266 public void valueChanged(TreeSelectionEvent event)
267 {
268 // Nothing selected in the collection tree
269 if (collection_tree.getSelectionCount() == 0) {
270 file_nodes = null;
271 }
272
273 // Some files selected in the collection tree
274 else {
275 TreePath paths[] = collection_tree.getSelectionPaths();
276 file_nodes = new CollectionTreeNode[paths.length];
277 for (int i = 0; i < paths.length; i++) {
278 file_nodes[i] = (CollectionTreeNode) paths[i].getLastPathComponent();
279 }
280 }
281
282 // Update the metadata value table (and consequently, the metadata value tree)
283 metadata_value_table_pane.stopEditingAndRebuild(file_nodes);
284 }
285
286
287 private class MetadataValueTableListSelectionListener
288 implements ListSelectionListener
289 {
290 public void valueChanged(ListSelectionEvent list_selection_event)
291 {
292 // We only want to handle one event per selection, so wait for the value to stabilise
293 if (list_selection_event.getValueIsAdjusting()) {
294 return;
295 }
296
297 // Update the metadata value tree for the current table selection
298 metadata_value_tree_pane.rebuild(metadata_value_table_pane.getSelectedMetadataValueTableEntry());
299 }
300 }
301
302
303 private class MetadataValueTableMouseListener
304 extends MouseAdapter
305 {
306 public void mouseClicked(MouseEvent mouse_event)
307 {
308 // We're only interested in clicks on the inherited column
309 if (metadata_value_table_pane.isMouseEventForInheritedMetadataValueTableColumn(mouse_event) == false) {
310 return;
311 }
312
313 // If the selected metadata is inherited, switch to the folder it came from
314 MetadataValueTableEntry selected_metadata_value_table_entry = metadata_value_table_pane.getSelectedMetadataValueTableEntry();
315 if (selected_metadata_value_table_entry.isInheritedMetadata()) {
316 collection_tree.setSelection(selected_metadata_value_table_entry.getFolderMetadataInheritedFrom());
317 }
318 }
319 }
320
321
322 private class MetadataValueTextFieldDocumentListener
323 implements DocumentListener
324 {
325 /** Gives notification that an attribute or set of attributes changed */
326 public void changedUpdate(DocumentEvent document_event) {
327 validate(document_event);
328 }
329
330 /** Gives notification that there was an insert into the document */
331 public void insertUpdate(DocumentEvent document_event) {
332 validate(document_event);
333 }
334
335 /** Gives notification that a portion of the document has been removed */
336 public void removeUpdate(DocumentEvent document_event) {
337 validate(document_event);
338 }
339
340
341 /** Ensures that the value tree is updated in response to changes in the value text field */
342 private void validate(DocumentEvent document_event)
343 {
344 try {
345 Document document = document_event.getDocument();
346 String metadata_value_string = document.getText(0, document.getLength());
347 metadata_value_tree_pane.selectBestPathForMetadataValue(metadata_value_string);
348 }
349 catch (Exception exception) {
350 DebugStream.printStackTrace(exception);
351 }
352 }
353 }
354
355
356 private class MetadataValueTextFieldKeyListener
357 extends KeyAdapter
358 {
359 /** Gives notification of key events on the text field */
360 public void keyPressed(KeyEvent key_event)
361 {
362 // Tab: Auto-complete what is selected in the metadata value tree
363 if (key_event.getKeyCode() == KeyEvent.VK_TAB) {
364 MetadataValueTreeNode selected_metadata_value_tree_node = metadata_value_tree_pane.getSelectedMetadataValueTreeNode();
365 if (selected_metadata_value_tree_node != null) {
366 metadata_value_table_pane.setMetadataValueTextFieldValue(selected_metadata_value_tree_node.getFullValue());
367 }
368
369 // We do not want this event to be processed by the table also
370 key_event.consume();
371 }
372
373 // Enter: save the current value then add a blank row for the selected metadata element
374 if (key_event.getKeyCode() == KeyEvent.VK_ENTER) {
375 metadata_value_table_pane.stopEditingAndAddBlankRowForSelectedMetadataElement();
376 }
377 }
378 }
379
380
381 private class MetadataValueTreeSelectionListener
382 implements TreeSelectionListener
383 {
384 public void valueChanged(TreeSelectionEvent tree_selection_event)
385 {
386 // When a node is selected in the tree, fill the metadata value text field with the selected node's value
387 MetadataValueTreeNode selected_metadata_value_tree_node = metadata_value_tree_pane.getSelectedMetadataValueTreeNode();
388 if (selected_metadata_value_tree_node != null) {
389 metadata_value_table_pane.setMetadataValueTextFieldValue(selected_metadata_value_tree_node.getFullValue());
390 }
391 }
392 }
393
394
395 /** This class listens for certain key presses, such as [Up] or [Down], -copied from Gather Pane */
396 private class KeyListenerImpl
397 extends KeyAdapter {
398 private boolean vk_left_pressed = false;
399 /** Called whenever a key that was pressed is released, it is this action that will cause the desired effects (this allows for the key event itself to be processed prior to this listener dealing with it). */
400 public void keyReleased(KeyEvent event) {
401 ///ystem.err.println("Key Release detected. " + event.getKeyCode());
402 if (event.getKeyCode() == KeyEvent.VK_UP || event.getKeyCode() == KeyEvent.VK_DOWN) {
403 DragTree tree = (DragTree)event.getSource();
404 // we need to manually do the up and down selections
405 boolean up = (event.getKeyCode() == KeyEvent.VK_UP);
406 int current_row = tree.getLeadSelectionRow();
407 tree.setImmediate(true);
408 if (up) {
409 if (current_row > 0) {
410 tree.clearSelection();
411 tree.setSelectionRow(current_row-1);
412 }
413 } else {
414 if (current_row < tree.getRowCount()-1){
415 tree.clearSelection();
416 tree.setSelectionRow(current_row+1);
417 }
418 }
419 tree.setImmediate(false);
420 }
421 else if (event.getKeyCode() == KeyEvent.VK_LEFT) {
422 // left key on a file shifts the selection to the parent folder
423 DragTree tree = (DragTree)event.getSource();
424 TreePath path = tree.getLeadSelectionPath();
425 if(path != null) {
426 File file = ((CollectionTreeNode) path.getLastPathComponent()).getFile();
427 if(file != null) {
428 if (file.isFile() || vk_left_pressed) {
429 vk_left_pressed = false;
430 TreePath parent_path = path.getParentPath();
431 if (parent_path != null && parent_path.getParentPath() != null) {
432 // if this file is in the top level folder, don't move the focus
433 tree.setImmediate(true);
434 tree.clearSelection();
435 tree.setSelectionPath(parent_path);
436 tree.setImmediate(false);
437 }
438 }
439 }
440 }
441 }
442 }
443
444 // we need to watch for left clicks on an unopened folder - should shift the focus to teh parent folder. But because there is some other mysterious key listener that does opening and closing folders on right and left clicks, we must detect the situation before the other handler has done its job, and process it after.
445 public void keyPressed(KeyEvent event) {
446 if (event.getKeyCode() == KeyEvent.VK_LEFT) {
447 // left key on closed directory shifts the selection to the parent folder
448 DragTree tree = (DragTree)event.getSource();
449 TreePath path = tree.getLeadSelectionPath();
450 if(path == null) return;
451 File file = ((CollectionTreeNode) path.getLastPathComponent()).getFile();
452 if(file == null) return;
453
454 if (file.isDirectory() && tree.isCollapsed(path)) {
455 vk_left_pressed = true;
456 }
457 }
458 }
459 }
460
461
462 /** A listener for right mouse button clicks over the collection tree. */
463 private class RightButtonListener
464 extends MouseAdapter {
465 /** Called whenever a mouse click occurs (right or left) over a target component.
466 * @param event A <strong>MouseEvent</strong> containing further information about the mouse click action.
467 * @see org.greenstone.gatherer.gui.EnrichPane.RightButtonMenu
468 */
469 public void mouseClicked(MouseEvent event) {
470 if (SwingUtilities.isRightMouseButton(event)) {
471 new RightButtonMenu(event);
472 }
473 }
474 }
475
476
477 /** When a user right-clicks within the collection tree they are presented with a small popup menu of context based options. This class provides such functionality.
478 */
479 private class RightButtonMenu
480 extends JPopupMenu
481 implements ActionListener {
482
483 /** The tree over which the right click action occurred. */
484 private DragTree tree = null;
485 /** The tree nodes selected when the right click action occurred. */
486 private TreePath[] selection_paths = null;
487 /** The file record over which the right click action occurred. */
488 private CollectionTreeNode node = null;
489
490 private JMenuItem collapse_folder = null;
491 private JMenuItem expand_folder = null;
492 private JMenuItem metaaudit = null;
493 private JMenuItem open_externally = null;
494
495
496 private RightButtonMenu(MouseEvent event)
497 {
498 super();
499 this.tree = collection_tree;
500
501 // Note we have to use setImmediate() with the set selction paths
502 // otherwise the selection doesn't get updated until after the
503 // popup comes up.
504
505 // the right click position
506 TreePath right_click_path = tree.getPathForLocation(event.getX(), event.getY());
507 if (right_click_path == null) {
508 // user has clicked outside of the tree, clear the selection
509 selection_paths = null;
510 tree.setImmediate(true);
511 tree.clearSelection();
512 tree.setImmediate(false);
513 } else {
514 // Get the paths currently selected in the tree
515 selection_paths = tree.getSelectionPaths();
516 if (selection_paths == null) {
517 // nothing currently selected - we shift the selection to
518 // the node that was right clicked on
519 selection_paths = new TreePath[1];
520 selection_paths[0] = right_click_path;
521 tree.setImmediate(true);
522 tree.setSelectionPath(right_click_path);
523 tree.setImmediate(false);
524 } else if (selection_paths.length == 1 && ! selection_paths[0].equals( right_click_path)) {
525 tree.setImmediate(true);
526 tree.clearSelection();
527 tree.setSelectionPath(right_click_path);
528 tree.setImmediate(false);
529 selection_paths[0] = right_click_path;
530 } else {
531 // we had multiply selected paths in the tree.
532 // if we clicked on one of those paths, then use all the
533 // current selection, otherwise clear the selection and
534 // select the one we right clicked on
535 boolean clicked_in_selection = false;
536 for (int i=0; i<selection_paths.length; i++) {
537 if (selection_paths[i].equals(right_click_path)) {
538 clicked_in_selection = true;
539 break;
540 }
541 }
542 if (!clicked_in_selection) {
543 // want the tree to update right away
544 tree.setImmediate(true);
545 tree.clearSelection();
546 tree.setSelectionPath(right_click_path);
547 tree.setImmediate(false);
548 selection_paths = new TreePath[1];
549 selection_paths[0] = right_click_path;
550 }
551 }
552 }
553 // finally we have the correct selection paths!
554
555 // Create an appropriate context menu, based on what is selected
556 buildContextMenu(selection_paths);
557
558 // Show the popup menu on screen
559 show(tree, event.getX(), event.getY());
560 }
561
562
563 private void buildContextMenu(TreePath[] selection_paths)
564 {
565 // If nothing is selected, no options are available
566 if (selection_paths == null) {
567 return;
568 }
569
570 DebugStream.println("Number of files/folders selected: " + selection_paths.length);
571
572 // Always have meta-audit option
573 metaaudit = new JMenuItem(Dictionary.get("Menu.Metadata_View", collection_tree.getSelectionDetails()), KeyEvent.VK_A);
574 metaaudit.addActionListener(this);
575 add(metaaudit);
576
577 // Only meta-audit is available if multiple items are selected...
578 if (selection_paths.length > 1) {
579 return;
580 }
581
582 TreePath path = selection_paths[0];
583 node = (CollectionTreeNode) path.getLastPathComponent();
584
585 // ---- Options for file nodes ----
586 if (node.isLeaf()) {
587 // Open the file in an external program
588 open_externally = new JMenuItem(Dictionary.get("Menu.Open_Externally"), KeyEvent.VK_O);
589 open_externally.addActionListener(this);
590 add(open_externally);
591 return;
592 }
593
594 // ---- Options for folder nodes ----
595 // Collapse or expand, depending on current status
596 if (tree.isExpanded(path)) {
597 collapse_folder = new JMenuItem(Dictionary.get("Menu.Collapse"), KeyEvent.VK_C);
598 collapse_folder.addActionListener(this);
599 add(collapse_folder);
600 }
601 else {
602 expand_folder = new JMenuItem(Dictionary.get("Menu.Expand"), KeyEvent.VK_O);
603 expand_folder.addActionListener(this);
604 add(expand_folder);
605 }
606 }
607
608
609 /** Called whenever one of the menu items is clicked, this method then causes the appropriate effect. */
610 public void actionPerformed(ActionEvent event)
611 {
612 Object source = event.getSource();
613
614 // Collapse folder
615 if (source == collapse_folder) {
616 tree.collapsePath(selection_paths[0]);
617 }
618
619 // Expand folder
620 else if (source == expand_folder) {
621 tree.expandPath(selection_paths[0]);
622 }
623
624 // Meta-audit
625 else if (source == metaaudit) {
626 Gatherer.g_man.showMetaAuditBox();
627 }
628
629 // Open in external program
630 else if (source == open_externally) {
631 Gatherer.f_man.openFileInExternalApplication(node.getFile());
632 }
633 }
634 }
635}
Note: See TracBrowser for help on using the repository browser.