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

Last change on this file since 15107 was 15107, checked in by ak19, 16 years ago

Added Refresh on rightclick AND now allows multiple selected documents to be replaced with GS-generated html versions (works with replace_srcdoc_with_html.pl)

  • Property svn:keywords set to Author Date Id Revision
File size: 14.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.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 refresh.addActionListener(this);
255 add(refresh);
256
257 node = (CollectionTreeNode) collection_tree.getModel().getRoot();
258 return;
259 }
260
261 // Meta-audit and delete options
262 metaaudit = new JMenuItem(Dictionary.get("Menu.Metadata_View", collection_tree.getSelectionDetails()), KeyEvent.VK_A);
263 metaaudit.addActionListener(this);
264 add(metaaudit);
265
266 delete = new JMenuItem(Dictionary.get("CollectionPopupMenu.Delete"), KeyEvent.VK_D);
267 delete.addActionListener(this);
268 add(delete);
269
270 // The src doc replaceable (with html file) option is only available when all files selected are of the
271 // same type (same extension). For srcreplaceable files only. Works with replace_srcdoc_with_html.pl
272 CollectionTreeNode firstSelectedNode = (CollectionTreeNode)selection_paths[0].getLastPathComponent();
273 if(firstSelectedNode.isSrcReplaceable()) { // test the first selected node
274 replace_srcdoc_with_html = new JMenuItem(Dictionary.get("Menu.Replace_SrcDoc_With_HTML"), KeyEvent.VK_H);
275 replace_srcdoc_with_html.addActionListener(this);
276 add(replace_srcdoc_with_html);
277
278 // Now the menu is there, grey it out if not all the files are of the same type
279 if(!selectedFilesOfSameType(selection_paths)) {
280 replace_srcdoc_with_html.setEnabled(false);
281 }
282 }
283
284 // Only meta-audit and delete (and possibly replace_srcdoc) are available if multiple items are selected...
285 if (selection_paths.length > 1) {
286 return;
287 }
288
289 // Rename option
290 rename = new JMenuItem(Dictionary.get("CollectionPopupMenu.Rename"), KeyEvent.VK_R);
291 rename.addActionListener(this);
292 add(rename);
293
294 TreePath path = selection_paths[0];
295 node = (CollectionTreeNode) path.getLastPathComponent();
296
297 // ---- Options for file nodes ----
298 if (node.isLeaf()) {
299 // Explode metadata databases, for explodable files only
300 if (node.isExplodable()) {
301 explode_metadata_database = new JMenuItem(Dictionary.get("Menu.Explode_Metadata_Database"), KeyEvent.VK_E);
302 explode_metadata_database.addActionListener(this);
303 add(explode_metadata_database);
304 }
305
306 // Replace file
307 // !! TO DO: Remote building
308 if (!Gatherer.isGsdlRemote) {
309 replace = new JMenuItem(Dictionary.get("CollectionPopupMenu.Replace"), KeyEvent.VK_P);
310 replace.addActionListener(this);
311 add(replace);
312 }
313
314 // Open the file in an external program
315 open_externally = new JMenuItem(Dictionary.get("Menu.Open_Externally"), KeyEvent.VK_O);
316 open_externally.addActionListener(this);
317 add(open_externally);
318
319 return;
320 }
321
322 // ---- Options for folder nodes ----
323 // Collapse or expand, depending on current status
324 if (collection_tree.isExpanded(path)) {
325 collapse_folder = new JMenuItem(Dictionary.get("Menu.Collapse"), KeyEvent.VK_C);
326 collapse_folder.addActionListener(this);
327 add(collapse_folder);
328 }
329 else {
330 expand_folder = new JMenuItem(Dictionary.get("Menu.Expand"), KeyEvent.VK_O);
331 expand_folder.addActionListener(this);
332 add(expand_folder);
333 }
334
335 // New folder/dummy doc options
336 if (!node.isReadOnly()) {
337 new_folder = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Folder"), KeyEvent.VK_N);
338 new_folder.addActionListener(this);
339 add(new_folder);
340
341 new_dummy_doc = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Dummy_Doc"));
342 new_dummy_doc.addActionListener(this);
343 add(new_dummy_doc);
344 }
345 }
346
347
348 /** Called whenever one of the menu items is clicked, this method then causes the appropriate effect. */
349 public void actionPerformed(ActionEvent event)
350 {
351 Object source = event.getSource();
352
353 // Collapse folder
354 if (source == collapse_folder) {
355 collection_tree.collapsePath(selection_paths[0]);
356 }
357
358 // Expand folder
359 else if (source == expand_folder) {
360 collection_tree.expandPath(selection_paths[0]);
361 }
362
363 // Explode metadata database
364 else if (source == explode_metadata_database) {
365 Gatherer.f_man.explodeMetadataDatabase(node.getFile());
366 }
367
368 // Replace source document with generated html (works with replace_srcdoc_with_html.pl)
369 else if (source == replace_srcdoc_with_html) {
370 java.io.File[] source_files = new java.io.File[selection_paths.length];
371 for (int i = 0; i < selection_paths.length; i++) {
372 CollectionTreeNode node = (CollectionTreeNode) selection_paths[i].getLastPathComponent();
373 source_files[i] = node.getFile();
374 }
375 Gatherer.f_man.replaceSrcDocWithHtml(source_files); // passing the selected files
376 }
377
378 // Delete
379 else if (source == delete) {
380 CollectionTreeNode[] source_nodes = new CollectionTreeNode[selection_paths.length];
381 for (int i = 0; i < selection_paths.length; i++) {
382 source_nodes[i] = (CollectionTreeNode) selection_paths[i].getLastPathComponent();
383 }
384
385 // Fire a delete action
386 Gatherer.f_man.action(collection_tree, source_nodes, Gatherer.recycle_bin, null);
387 }
388
389 // Meta-audit
390 else if (source == metaaudit) {
391 Gatherer.g_man.showMetaAuditBox();
392 }
393
394 // New folder
395 else if (source == new_folder) {
396 Gatherer.f_man.newFolder(collection_tree, node);
397 }
398
399 // New dummy doc
400 else if (source == new_dummy_doc) {
401 Gatherer.f_man.newDummyDoc(collection_tree, node);
402 }
403
404 // Refresh action to reload folder view
405 else if (source == refresh) { // Refresh collection tree
406 Gatherer.g_man.refreshCollectionTree(DragTree.COLLECTION_CONTENTS_CHANGED);
407 }
408
409 // Open in external program
410 else if (source == open_externally) {
411 Gatherer.f_man.openFileInExternalApplication(node.getFile());
412 }
413
414 // Rename
415 else if (source == rename) {
416 Gatherer.f_man.renameCollectionFile(collection_tree, node);
417 }
418
419 // Replace
420 else if (source == replace) {
421 Gatherer.f_man.replaceCollectionFile(collection_tree, node);
422 }
423 }
424 }
425}
Note: See TracBrowser for help on using the repository browser.