source: main/trunk/gli/src/org/greenstone/gatherer/file/WorkspaceTree.java@ 22605

Last change on this file since 22605 was 22605, checked in by ak19, 14 years ago

Ticket #152: Allowing different paths to collect dir so that GLI can work with collect dirs on pen drives. NONE OF THESE CHANGES ARE FOR Client-GLI AS YET. 1. Preferences (Connection tab), Open and New Collection dialogs allow one to change the current collect directory containing the collections to select from. 2. New Collection dialog allows one to base a new collection on an existing collection in a collect dir other than the current collect dir. 3. Collections in the Documents in Greenstone Collections Workspace Tree Node now have two additional rightclick options: to move and copy these collections to another location.

  • Property svn:keywords set to Author Date Id Revision
File size: 15.9 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 *
9 * Copyright (C) 2006 New Zealand Digital Library Project
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *############################################################################
25 */
26
27package org.greenstone.gatherer.file;
28
29import java.awt.event.*;
30import java.io.File;
31import java.util.Enumeration;
32import javax.swing.*;
33import javax.swing.tree.TreePath;
34import org.greenstone.gatherer.Configuration;
35import org.greenstone.gatherer.DebugStream;
36import org.greenstone.gatherer.Dictionary;
37import org.greenstone.gatherer.Gatherer;
38import org.greenstone.gatherer.collection.CollectionManager;
39import org.greenstone.gatherer.gui.CreateShortcutPrompt;
40import org.greenstone.gatherer.gui.tree.DragTree;
41import org.greenstone.gatherer.util.Utility;
42
43
44public class WorkspaceTree
45 extends DragTree
46 implements MouseListener
47{
48 static public final int LIBRARY_CONTENTS_CHANGED = 10;
49 static public final int DOWNLOADED_FILES_CHANGED = 11;
50 static public final int FOLDER_SHORTCUTS_CHANGED = 12;
51
52
53 public WorkspaceTree()
54 {
55 super(WorkspaceTreeModel.getWorkspaceTreeModel(), true);
56 addMouseListener(this);
57
58 setBackgroundNonSelectionColor(Configuration.getColor("coloring.workspace_tree_background", false));
59 setBackgroundSelectionColor(Configuration.getColor("coloring.workspace_selection_background", false));
60 setTextNonSelectionColor(Configuration.getColor("coloring.workspace_tree_foreground", false));
61 setTextSelectionColor(Configuration.getColor("coloring.workspace_selection_foreground", false));
62
63 filter.setBackground(Configuration.getColor("coloring.workspace_heading_background", false));
64 filter.setEditable(Configuration.getMode() >= Configuration.LIBRARIAN_MODE);
65 }
66
67
68 public void addDirectoryMapping(String name, File file)
69 {
70 // Update the information stored in the user's configuration
71 Configuration.addDirectoryMapping(name, file);
72
73 // Now update the tree
74 refresh(FOLDER_SHORTCUTS_CHANGED);
75 }
76
77
78 public boolean isDraggable()
79 {
80 return true;
81 }
82
83
84 public boolean isDroppable()
85 {
86 return false;
87 }
88
89
90 public void mouseClicked(MouseEvent event)
91 {
92 if (SwingUtilities.isRightMouseButton(event)) {
93 new WorkspaceTreeRightClickMenu(this, event);
94 }
95 }
96
97 public void mouseEntered(MouseEvent event) { }
98
99 public void mouseExited(MouseEvent event) { }
100
101 public void mousePressed(MouseEvent event) { }
102
103 public void mouseReleased(MouseEvent event) { }
104
105
106 public void refresh(int refresh_reason)
107 {
108 DebugStream.println("WorkspaceTree::refresh()... ");
109
110 // The method for displaying the tree has changed - redraw the tree
111 if (refresh_reason == DragTree.TREE_DISPLAY_CHANGED) {
112 DebugStream.println("...Reason: tree display changed.");
113 updateUI();
114 }
115
116 // The loaded collection has changed - currently do nothing
117 if (refresh_reason == DragTree.LOADED_COLLECTION_CHANGED) {
118 DebugStream.println("...Reason: loaded collection changed.");
119 }
120
121 // The collection's contents have changed - refresh collection's import folder
122 if (refresh_reason == DragTree.COLLECTION_CONTENTS_CHANGED) {
123 DebugStream.println("...Reason: collection contents changed.");
124 String collection_import_directory_path = CollectionManager.getLoadedCollectionImportDirectoryPath();
125 refreshEveryNodeShowingFolder(collection_import_directory_path);
126 }
127
128 // The collections in the library have changed - refresh the collect directory
129 if (refresh_reason == WorkspaceTree.LIBRARY_CONTENTS_CHANGED) {
130 DebugStream.println("...Reason: library contents changed.");
131 String collect_directory_path = Gatherer.getCollectDirectoryPath();
132 refreshEveryNodeShowingFolder(collect_directory_path);
133 WorkspaceTreeModel.refreshGreenstoneCollectionsNode();
134 }
135
136 // The downloaded files have changed - refresh that node
137 if (refresh_reason == WorkspaceTree.DOWNLOADED_FILES_CHANGED) {
138 DebugStream.println("...Reason: downloaded files changed.");
139 WorkspaceTreeModel.refreshDownloadedFilesNode();
140 }
141
142 // The folder shortcuts have changed - refresh only them
143 if (refresh_reason == WorkspaceTree.FOLDER_SHORTCUTS_CHANGED) {
144 DebugStream.println("...Reason: folder shortcuts changed.");
145 WorkspaceTreeModel.refreshFolderShortcuts();
146 }
147 }
148
149
150 private void refreshEveryNodeShowingFolder(String folder_path_str)
151 {
152 // Search through the expanded tree paths, checking if any show the given folder
153 TreePath tree_root_path = new TreePath(getModel().getRoot());
154 Enumeration expanded_tree_paths = getExpandedDescendants(tree_root_path);
155 while (expanded_tree_paths.hasMoreElements()) {
156 TreePath expanded_tree_path = (TreePath) expanded_tree_paths.nextElement();
157 WorkspaceTreeNode tree_node = (WorkspaceTreeNode) expanded_tree_path.getLastPathComponent();
158
159 File tree_node_file = tree_node.getFile();
160 if (tree_node_file == null) {
161 continue;
162 }
163
164 // Get the path of the open tree node
165 String tree_node_path_str = tree_node_file.toString();
166 if (!tree_node_path_str.endsWith(File.separator)) {
167 tree_node_path_str = tree_node_path_str + File.separator;
168 }
169
170 // If the specified folder is open, it must be refreshed
171 if (tree_node_path_str.equals(folder_path_str)) {
172 //System.err.println("Must refresh node " + tree_node_path_str + "!");
173 ((WorkspaceTreeModel) getModel()).refresh(expanded_tree_path);
174 }
175 }
176 }
177
178
179 public void removeDirectoryMapping(WorkspaceTreeNode target)
180 {
181 // Update the information stored in the user's configuration
182 Configuration.removeDirectoryMapping(target.toString());
183
184 // Update tree
185 refresh(FOLDER_SHORTCUTS_CHANGED);
186 }
187
188
189 public String toString()
190 {
191 return "Workspace";
192 }
193
194
195 /** When a user right-clicks within the workspace and collection trees they are presented with a small popup menu of context based options. This class provides such functionality.
196 */
197 private class WorkspaceTreeRightClickMenu
198 extends JPopupMenu
199 implements ActionListener
200 {
201 /** The tree over which the right click action occurred. */
202 private WorkspaceTree workspace_tree = null;
203 /** The tree nodes selected when the right click action occurred. */
204 private TreePath[] selection_paths = null;
205 /** The file record over which the right click action occurred. */
206 private WorkspaceTreeNode node = null;
207
208 private JMenuItem create_shortcut = null;
209 private JMenuItem delete_shortcut = null;
210 private JMenuItem collapse_folder = null;
211 private JMenuItem expand_folder = null;
212 private JMenuItem explode_metadata_database = null;
213 private JMenuItem delete = null;
214 private JMenuItem metaaudit = null;
215 private JMenuItem new_folder = null;
216 private JMenuItem new_dummy_doc = null;
217 private JMenuItem open_externally = null;
218 private JMenuItem rename = null;
219 private JMenuItem replace = null;
220 private JMenuItem copy_collection = null;
221 private JMenuItem move_collection = null;
222
223
224 private WorkspaceTreeRightClickMenu(WorkspaceTree workspace_tree, MouseEvent event)
225 {
226 super();
227 this.workspace_tree = workspace_tree;
228
229 // Note we have to use setImmediate() with the set selction paths
230 // otherwise the selection doesn't get updated until after the
231 // popup comes up.
232
233 // the right click position
234 TreePath right_click_path = workspace_tree.getPathForLocation(event.getX(), event.getY());
235 if (right_click_path == null) {
236 // user has clicked outside of the tree, clear the selection
237 selection_paths = null;
238 workspace_tree.setImmediate(true);
239 workspace_tree.clearSelection();
240 workspace_tree.setImmediate(false);
241 }
242 else {
243 // Get the paths currently selected in the tree
244 selection_paths = workspace_tree.getSelectionPaths();
245 if (selection_paths == null) {
246 // nothing currently selected - we shift the selection to
247 // the node that was right clicked on
248 selection_paths = new TreePath[1];
249 selection_paths[0] = right_click_path;
250 workspace_tree.setImmediate(true);
251 workspace_tree.setSelectionPath(right_click_path);
252 workspace_tree.setImmediate(false);
253 }
254 else if (selection_paths.length == 1 && ! selection_paths[0].equals( right_click_path)) {
255 workspace_tree.setImmediate(true);
256 workspace_tree.clearSelection();
257 workspace_tree.setSelectionPath(right_click_path);
258 workspace_tree.setImmediate(false);
259 selection_paths[0] = right_click_path;
260 }
261 else {
262 // we had multiply selected paths in the tree.
263 // if we clicked on one of those paths, then use all the
264 // current selection, otherwise clear the selection and
265 // select the one we right clicked on
266 boolean clicked_in_selection = false;
267 for (int i = 0; i < selection_paths.length; i++) {
268 if (selection_paths[i].equals(right_click_path)) {
269 clicked_in_selection = true;
270 break;
271 }
272 }
273 if (!clicked_in_selection) {
274 // want the tree to update right away
275 workspace_tree.setImmediate(true);
276 workspace_tree.clearSelection();
277 workspace_tree.setSelectionPath(right_click_path);
278 workspace_tree.setImmediate(false);
279 selection_paths = new TreePath[1];
280 selection_paths[0] = right_click_path;
281 }
282 }
283 }
284
285 // Create an appropriate context menu, based on what is selected
286 buildContextMenu(selection_paths);
287
288 // Show the popup menu on screen
289 show(workspace_tree, event.getX(), event.getY());
290 }
291
292
293 private void buildContextMenu(TreePath[] selection_paths)
294 {
295 // If nothing is selected, no options are available...
296 if (selection_paths == null) {
297 return;
298 }
299
300 // Only meta-audit and delete are available if multiple items are selected...
301 if (selection_paths.length > 1) {
302 return;
303 }
304
305 TreePath path = selection_paths[0];
306 node = (WorkspaceTreeNode) path.getLastPathComponent();
307
308 // ---- Options for file nodes ----
309 if (node.isLeaf()) {
310 // Open the file in an external program
311 open_externally = new JMenuItem(Dictionary.get("Menu.Open_Externally"), KeyEvent.VK_O);
312 open_externally.addActionListener(this);
313 add(open_externally);
314
315 return;
316 }
317
318 // ---- Options for folder nodes ----
319 // Collapse or expand, depending on current status
320 if (workspace_tree.isExpanded(path)) {
321 collapse_folder = new JMenuItem(Dictionary.get("Menu.Collapse"), KeyEvent.VK_C);
322 collapse_folder.addActionListener(this);
323 add(collapse_folder);
324 }
325 else {
326 expand_folder = new JMenuItem(Dictionary.get("Menu.Expand"), KeyEvent.VK_O);
327 expand_folder.addActionListener(this);
328 add(expand_folder);
329 }
330
331 // Create/remove shortcut option, for workspace tree only
332 if (workspace_tree == workspace_tree) {
333 // The "built-in" folders can't be modified
334 String node_name = node.toString();
335 if (node_name.equals(Dictionary.get("Tree.World")) || node_name.equals(Dictionary.get("Tree.Root")) || node_name.equals(Dictionary.get("Tree.DownloadedFiles"))) {
336 return;
337 }
338
339 // You can unmap 1st level nodes
340 WorkspaceTreeNode root = (WorkspaceTreeNode) workspace_tree.getModel().getRoot();
341 if (root.getIndex(node) != -1) {
342 delete_shortcut = new JMenuItem(Dictionary.get("MappingPrompt.Unmap"), KeyEvent.VK_R);
343 delete_shortcut.addActionListener(this);
344 add(delete_shortcut);
345 }
346 // Or map any other level directories
347 else {
348 // --- Options for Documents In Greenstone Collections (greenstone_collections_node) ---
349 // all subfolder of Documents In Greenstone Collections can be copied and moved
350 WorkspaceTreeNode secondLevelNode = (WorkspaceTreeNode) path.getPathComponent(1);
351
352 if (secondLevelNode.toString().equals(Dictionary.get("Tree.World"))) {
353 // Can move and copy the collection folders across
354 copy_collection = new JMenuItem(Dictionary.get("Menu.Copy_Collection"), KeyEvent.VK_P);
355 copy_collection.addActionListener(this);
356 add(copy_collection);
357
358 move_collection = new JMenuItem(Dictionary.get("Menu.Move_Collection"), KeyEvent.VK_M);
359 move_collection.addActionListener(this);
360 add(move_collection);
361 }
362
363 create_shortcut = new JMenuItem(Dictionary.get("MappingPrompt.Map"), KeyEvent.VK_S);
364 create_shortcut.addActionListener(this);
365 add(create_shortcut);
366 }
367 }
368 }
369
370
371 /** Called whenever one of the menu items is clicked, this method then causes the appropriate effect. */
372 public void actionPerformed(ActionEvent event)
373 {
374 Object source = event.getSource();
375
376 // Create shortcut
377 if (source == create_shortcut) {
378 //Make sure the file exists
379 if(!node.getFile().exists()){
380 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("FileActions.Folder_Does_Not_Exist"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
381 return;
382 }
383 CreateShortcutPrompt csp = new CreateShortcutPrompt(workspace_tree, node.getFile());
384 csp.destroy();
385 }
386
387 // Delete shortcut
388 else if (source == delete_shortcut) {
389 workspace_tree.removeDirectoryMapping(node);
390 }
391
392 // Collapse folder
393 else if (source == collapse_folder) {
394 workspace_tree.collapsePath(selection_paths[0]);
395 }
396
397 // Expand folder
398 else if (source == expand_folder) {
399 workspace_tree.expandPath(selection_paths[0]);
400 }
401
402 // Open in external program
403 else if (source == open_externally) {
404 Gatherer.f_man.openFileInExternalApplication(node.getFile());
405 }
406
407 // Copy or move a collection from Documents in Greenstone Collections
408 else if (source == move_collection || source == copy_collection) {
409
410 JFileChooser chooser = new JFileChooser(Gatherer.getCollectDirectoryPath());
411 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
412 chooser.setDialogTitle(Dictionary.get("FileActions.ChooseDestinationDirectory"));
413 int returnVal = chooser.showOpenDialog(Gatherer.g_man.gather_pane);
414
415 if(returnVal == JFileChooser.APPROVE_OPTION) {
416
417 // the node that the user rightclicked on ends up
418 // being the col's import folder
419 File sourceFolder = node.getFile();
420 if(sourceFolder.getName().equals("import")) {
421 sourceFolder = sourceFolder.getParentFile();
422 }
423 String target = chooser.getSelectedFile().getAbsolutePath();
424 File targetFolder = new File(target+File.separator+sourceFolder.getName());
425
426 // some sanity checks
427 if(targetFolder.equals(sourceFolder)) { // directory has not changed. No copy/move performed
428 JOptionPane.showMessageDialog(Gatherer.g_man,
429 "Can't move " + sourceFolder + " " + "to itself\n(" + targetFolder + ").",
430 "Source and destination directories are the same",
431 JOptionPane.ERROR_MESSAGE);
432 return;
433 } else if(targetFolder.exists()) { // option to overwrite or not
434 if(JOptionPane.showConfirmDialog(Gatherer.g_man,
435 "Directory " + targetFolder + " already exists. Overwrite?",
436 "Destination directory already exists",
437 JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
438 return;
439 }
440 // else can overwrite: delete the existing targetfolder before copying/moving
441 Utility.delete(targetFolder);
442 }
443
444 int operation = (source == move_collection) ? FileManager.MOVE : FileManager.COPY;
445 Gatherer.f_man.action(sourceFolder, targetFolder, operation);
446 }
447 }
448 }
449 }
450}
Note: See TracBrowser for help on using the repository browser.