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

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

Tidied up the way collections are saved and closed, and added some stuff in preparation for uploading metadata files to the server.

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