source: gli/trunk/src/org/greenstone/gatherer/collection/CollectionTree.java@ 19231

Last change on this file since 19231 was 19231, checked in by ak19, 15 years ago

Making rename shortcut option work for the remote case.

  • Property svn:keywords set to Author Date Id Revision
File size: 15.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 *
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.collection;
28
29import java.awt.*;
30import java.awt.event.*;
31import javax.swing.*;
32import javax.swing.tree.*;
33import org.greenstone.gatherer.Configuration;
34import org.greenstone.gatherer.Dictionary;
35import org.greenstone.gatherer.Gatherer;
36import org.greenstone.gatherer.gui.tree.DragTree;
37import org.greenstone.gatherer.gui.tree.DragTreeCellRenderer;
38
39
40public class CollectionTree
41 extends DragTree
42 implements MouseListener
43{
44 public CollectionTree(CollectionTreeModel collection_tree_model, boolean mixed_selection)
45 {
46 super(collection_tree_model, mixed_selection);
47 addMouseListener(this);
48
49 setCellRenderer(new CollectionTreeCellRenderer());
50 setBackgroundNonSelectionColor(Configuration.getColor("coloring.collection_tree_background", false));
51 setBackgroundSelectionColor(Configuration.getColor("coloring.collection_selection_background", false));
52 setTextNonSelectionColor(Configuration.getColor("coloring.collection_tree_foreground", false));
53 setTextSelectionColor(Configuration.getColor("coloring.collection_selection_foreground", false));
54
55 filter.setBackground(Configuration.getColor("coloring.collection_heading_background", false));
56 filter.setEditable(Configuration.getMode() >= Configuration.LIBRARIAN_MODE);
57 }
58
59
60 public boolean isDraggable()
61 {
62 return true;
63 }
64
65
66 public boolean isDroppable()
67 {
68 return true;
69 }
70
71
72 public void mouseClicked(MouseEvent event)
73 {
74 if (SwingUtilities.isRightMouseButton(event)) {
75 new CollectionTreeRightClickMenu(this, event);
76 }
77 }
78
79 public void mouseEntered(MouseEvent event) { }
80
81 public void mouseExited(MouseEvent event) { }
82
83 public void mousePressed(MouseEvent event) { }
84
85 public void mouseReleased(MouseEvent event) { }
86
87
88 public String toString()
89 {
90 return "Collection";
91 }
92
93
94 private class CollectionTreeCellRenderer
95 extends DragTreeCellRenderer
96 {
97 public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus)
98 {
99 JLabel tree_cell = (JLabel) super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
100
101 // Mark explodable files and SrcReplaceable files with a different icon (Green file icon)
102 if(value instanceof CollectionTreeNode) {
103 if(((CollectionTreeNode) value).isExplodable() || ((CollectionTreeNode) value).isSrcReplaceable()) {
104 tree_cell.setIcon(CollectionTreeNode.GREEN_FILE_ICON);
105 }
106 }
107
108 return tree_cell;
109 }
110 }
111
112
113 /** 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.
114 */
115 private class CollectionTreeRightClickMenu
116 extends JPopupMenu
117 implements ActionListener
118 {
119 /** The tree over which the right click action occurred. */
120 private CollectionTree collection_tree = null;
121 /** The tree nodes selected when the right click action occurred. */
122 private TreePath[] selection_paths = null;
123 /** The file record over which the right click action occurred. */
124 private CollectionTreeNode node = null;
125
126 private JMenuItem collapse_folder = null;
127 private JMenuItem expand_folder = null;
128 private JMenuItem explode_metadata_database = null;
129 private JMenuItem replace_srcdoc_with_html = null;
130 private JMenuItem delete = null;
131 private JMenuItem metaaudit = null;
132 private JMenuItem new_folder = null;
133 private JMenuItem new_dummy_doc = null;
134 private JMenuItem refresh = null; // for refreshing folder view
135 private JMenuItem open_externally = null;
136 private JMenuItem rename = null;
137 private JMenuItem replace = null;
138
139
140 private CollectionTreeRightClickMenu(CollectionTree collection_tree, MouseEvent event)
141 {
142 super();
143 this.collection_tree = collection_tree;
144
145 // Note we have to use setImmediate() with the set selction paths
146 // otherwise the selection doesn't get updated until after the
147 // popup comes up.
148
149 // the right click position
150 TreePath right_click_path = collection_tree.getPathForLocation(event.getX(), event.getY());
151 if (right_click_path == null) {
152 // user has clicked outside of the tree, clear the selection
153 selection_paths = null;
154 collection_tree.setImmediate(true);
155 collection_tree.clearSelection();
156 collection_tree.setImmediate(false);
157 }
158 else {
159 // Get the paths currently selected in the tree
160 selection_paths = collection_tree.getSelectionPaths();
161 if (selection_paths == null) {
162 // nothing currently selected - we shift the selection to
163 // the node that was right clicked on
164 selection_paths = new TreePath[1];
165 selection_paths[0] = right_click_path;
166 collection_tree.setImmediate(true);
167 collection_tree.setSelectionPath(right_click_path);
168 collection_tree.setImmediate(false);
169 }
170 else if (selection_paths.length == 1 && ! selection_paths[0].equals( right_click_path)) {
171 collection_tree.setImmediate(true);
172 collection_tree.clearSelection();
173 collection_tree.setSelectionPath(right_click_path);
174 collection_tree.setImmediate(false);
175 selection_paths[0] = right_click_path;
176 }
177 else {
178 // we had multiply selected paths in the tree.
179 // if we clicked on one of those paths, then use all the
180 // current selection, otherwise clear the selection and
181 // select the one we right clicked on
182 boolean clicked_in_selection = false;
183 for (int i = 0; i < selection_paths.length; i++) {
184 if (selection_paths[i].equals(right_click_path)) {
185 clicked_in_selection = true;
186 break;
187 }
188 }
189 if (!clicked_in_selection) {
190 // want the tree to update right away
191 collection_tree.setImmediate(true);
192 collection_tree.clearSelection();
193 collection_tree.setSelectionPath(right_click_path);
194 collection_tree.setImmediate(false);
195 selection_paths = new TreePath[1];
196 selection_paths[0] = right_click_path;
197 }
198 }
199 }
200
201 // Create an appropriate context menu, based on what is selected
202 buildContextMenu(selection_paths);
203
204 // Show the popup menu on screen
205 show(collection_tree, event.getX(), event.getY());
206 }
207
208 /** Checks whether the files selected are of the same filetype (have the same extension).
209 * @param selectedFilePaths - the full file paths to the treenodes selected in the
210 * collection fileview.
211 * @return true if the file extensions of all the selected files are the same. False is
212 * returned if the file extension of any selected file is different (this means that if
213 * a folder was selected, false would be returned). False is also returned if nothing was
214 * selected.
215 * For use with replace_srcdoc_with_html.pl
216 */
217 private boolean selectedFilesOfSameType(TreePath[] selectedFilePaths) {
218 if(selectedFilePaths == null || selectedFilePaths.length <= 0)
219 return false;
220
221 boolean sameExtension = true;
222
223 // get just the filename from the path and extract its extension
224 String firstFile = selectedFilePaths[0].getLastPathComponent().toString();
225 int period = firstFile.lastIndexOf('.');
226 if(period == -1) { // someone could have selected a folder
227 return false;
228 }
229 String extension = firstFile.substring(period); // includes period
230
231 // compare with the other selected files' extensions:
232 for(int i = 1; i < selectedFilePaths.length && sameExtension; i++) {
233 String otherFile = selectedFilePaths[i].getLastPathComponent().toString();
234 String otherFileExt = otherFile.substring(otherFile.lastIndexOf('.'));
235 if(!extension.equals(otherFileExt))
236 sameExtension = false;
237 }
238 return sameExtension;
239 }
240
241 private void buildContextMenu(TreePath[] selection_paths)
242 {
243 // If nothing is selected, only the new folder/dummy doc options are available...
244 if (selection_paths == null) {
245 new_folder = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Folder"), KeyEvent.VK_N);
246 new_folder.addActionListener(this);
247 add(new_folder);
248
249 new_dummy_doc = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Dummy_Doc"));
250 new_dummy_doc.addActionListener(this);
251 add(new_dummy_doc);
252
253 refresh = new JMenuItem(Dictionary.get("CollectionPopupMenu.Refresh"));
254 if(Gatherer.isGsdlRemote) {
255 refresh.setEnabled(false);
256 }
257 refresh.addActionListener(this);
258 add(refresh);
259
260 node = (CollectionTreeNode) collection_tree.getModel().getRoot();
261 return;
262 }
263
264 // Meta-audit and delete options
265 metaaudit = new JMenuItem(Dictionary.get("Menu.Metadata_View", collection_tree.getSelectionDetails()), KeyEvent.VK_A);
266 metaaudit.addActionListener(this);
267 add(metaaudit);
268
269 delete = new JMenuItem(Dictionary.get("CollectionPopupMenu.Delete"), KeyEvent.VK_D);
270 delete.addActionListener(this);
271 add(delete);
272
273 // The src doc replaceable (with html file) option is only available when all files selected are of the
274 // same type (same extension). For srcreplaceable files only. Works with replace_srcdoc_with_html.pl
275 CollectionTreeNode firstSelectedNode = (CollectionTreeNode)selection_paths[0].getLastPathComponent();
276 if(firstSelectedNode.isSrcReplaceable()) { // test the first selected node
277 replace_srcdoc_with_html = new JMenuItem(Dictionary.get("Menu.Replace_SrcDoc_With_HTML"), KeyEvent.VK_H);
278 replace_srcdoc_with_html.addActionListener(this);
279 add(replace_srcdoc_with_html);
280
281 // Now the menu is there, grey it out if not all the files are of the same type
282 if(!selectedFilesOfSameType(selection_paths)) {
283 replace_srcdoc_with_html.setEnabled(false);
284 }
285 }
286
287 // Only meta-audit and delete (and possibly replace_srcdoc) are available if multiple items are selected...
288 if (selection_paths.length > 1) {
289 return;
290 }
291
292 // Rename option
293 rename = new JMenuItem(Dictionary.get("CollectionPopupMenu.Rename"), KeyEvent.VK_R);
294 rename.addActionListener(this);
295 add(rename);
296
297 TreePath path = selection_paths[0];
298 node = (CollectionTreeNode) path.getLastPathComponent();
299
300 // ---- Options for file nodes ----
301 if (node.isLeaf()) {
302 // Explode metadata databases, for explodable files only
303 if (node.isExplodable()) {
304 explode_metadata_database = new JMenuItem(Dictionary.get("Menu.Explode_Metadata_Database"), KeyEvent.VK_E);
305 explode_metadata_database.addActionListener(this);
306 add(explode_metadata_database);
307 }
308
309 // Replace file
310 // !! TO DO: Remote building
311 replace = new JMenuItem(Dictionary.get("CollectionPopupMenu.Replace"), KeyEvent.VK_P);
312 replace.addActionListener(this);
313 add(replace);
314 if (Gatherer.isGsdlRemote) {
315 replace.setEnabled(false);
316 }
317 // Open the file in an external program
318 open_externally = new JMenuItem(Dictionary.get("Menu.Open_Externally"), KeyEvent.VK_O);
319 open_externally.addActionListener(this);
320 add(open_externally);
321
322 return;
323 }
324
325 // ---- Options for folder nodes ----
326 // Collapse or expand, depending on current status
327 if (collection_tree.isExpanded(path)) {
328 collapse_folder = new JMenuItem(Dictionary.get("Menu.Collapse"), KeyEvent.VK_C);
329 collapse_folder.addActionListener(this);
330 add(collapse_folder);
331 }
332 else {
333 expand_folder = new JMenuItem(Dictionary.get("Menu.Expand"), KeyEvent.VK_O);
334 expand_folder.addActionListener(this);
335 add(expand_folder);
336 }
337
338 // New folder/dummy doc options
339 if (!node.isReadOnly()) {
340 new_folder = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Folder"), KeyEvent.VK_N);
341 new_folder.addActionListener(this);
342 add(new_folder);
343
344 new_dummy_doc = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Dummy_Doc"));
345 new_dummy_doc.addActionListener(this);
346 add(new_dummy_doc);
347 }
348 }
349
350
351 /** Called whenever one of the menu items is clicked, this method then causes the appropriate effect. */
352 public void actionPerformed(ActionEvent event)
353 {
354 Object source = event.getSource();
355
356 // Collapse folder
357 if (source == collapse_folder) {
358 collection_tree.collapsePath(selection_paths[0]);
359 }
360
361 // Expand folder
362 else if (source == expand_folder) {
363 collection_tree.expandPath(selection_paths[0]);
364 }
365
366 // Explode metadata database
367 else if (source == explode_metadata_database) {
368 Gatherer.f_man.explodeMetadataDatabase(node.getFile());
369 }
370
371 // Replace source document with generated html (works with replace_srcdoc_with_html.pl)
372 else if (source == replace_srcdoc_with_html) {
373 java.io.File[] source_files = new java.io.File[selection_paths.length];
374 for (int i = 0; i < selection_paths.length; i++) {
375 CollectionTreeNode node = (CollectionTreeNode) selection_paths[i].getLastPathComponent();
376 source_files[i] = node.getFile();
377 }
378 Gatherer.f_man.replaceSrcDocWithHtml(source_files); // passing the selected files
379 }
380
381 // Delete
382 else if (source == delete) {
383 CollectionTreeNode[] source_nodes = new CollectionTreeNode[selection_paths.length];
384 for (int i = 0; i < selection_paths.length; i++) {
385 source_nodes[i] = (CollectionTreeNode) selection_paths[i].getLastPathComponent();
386 }
387
388 // Fire a delete action
389 Gatherer.f_man.action(collection_tree, source_nodes, Gatherer.recycle_bin, null);
390 }
391
392 // Meta-audit
393 else if (source == metaaudit) {
394 Gatherer.g_man.showMetaAuditBox();
395 }
396
397 // New folder
398 else if (source == new_folder) {
399 Gatherer.f_man.newFolder(collection_tree, node);
400 }
401
402 // New dummy doc
403 else if (source == new_dummy_doc) {
404 Gatherer.f_man.newDummyDoc(collection_tree, node);
405 }
406
407 // Refresh action to reload folder view
408 else if (source == refresh) { // Refresh collection tree
409 Gatherer.g_man.refreshCollectionTree(DragTree.COLLECTION_CONTENTS_CHANGED);
410 }
411
412 // Open in external program
413 else if (source == open_externally) {
414 Gatherer.f_man.openFileInExternalApplication(node.getFile());
415 }
416
417 // Rename
418 else if (source == rename) {
419 Gatherer.f_man.renameCollectionFile(collection_tree, node);
420 }
421
422 // Replace
423 else if (source == replace) {
424 Gatherer.f_man.replaceCollectionFile(collection_tree, node);
425 }
426 }
427 }
428}
Note: See TracBrowser for help on using the repository browser.