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

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

Making replace shortcut option work for the remote case.

  • 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 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 replace = new JMenuItem(Dictionary.get("CollectionPopupMenu.Replace"), KeyEvent.VK_P);
311 replace.addActionListener(this);
312 add(replace);
313 // Open the file in an external program
314 open_externally = new JMenuItem(Dictionary.get("Menu.Open_Externally"), KeyEvent.VK_O);
315 open_externally.addActionListener(this);
316 add(open_externally);
317
318 return;
319 }
320
321 // ---- Options for folder nodes ----
322 // Collapse or expand, depending on current status
323 if (collection_tree.isExpanded(path)) {
324 collapse_folder = new JMenuItem(Dictionary.get("Menu.Collapse"), KeyEvent.VK_C);
325 collapse_folder.addActionListener(this);
326 add(collapse_folder);
327 }
328 else {
329 expand_folder = new JMenuItem(Dictionary.get("Menu.Expand"), KeyEvent.VK_O);
330 expand_folder.addActionListener(this);
331 add(expand_folder);
332 }
333
334 // New folder/dummy doc options
335 if (!node.isReadOnly()) {
336 new_folder = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Folder"), KeyEvent.VK_N);
337 new_folder.addActionListener(this);
338 add(new_folder);
339
340 new_dummy_doc = new JMenuItem(Dictionary.get("CollectionPopupMenu.New_Dummy_Doc"));
341 new_dummy_doc.addActionListener(this);
342 add(new_dummy_doc);
343 }
344 }
345
346
347 /** Called whenever one of the menu items is clicked, this method then causes the appropriate effect. */
348 public void actionPerformed(ActionEvent event)
349 {
350 Object source = event.getSource();
351
352 // Collapse folder
353 if (source == collapse_folder) {
354 collection_tree.collapsePath(selection_paths[0]);
355 }
356
357 // Expand folder
358 else if (source == expand_folder) {
359 collection_tree.expandPath(selection_paths[0]);
360 }
361
362 // Explode metadata database
363 else if (source == explode_metadata_database) {
364 Gatherer.f_man.explodeMetadataDatabase(node.getFile());
365 }
366
367 // Replace source document with generated html (works with replace_srcdoc_with_html.pl)
368 else if (source == replace_srcdoc_with_html) {
369 java.io.File[] source_files = new java.io.File[selection_paths.length];
370 for (int i = 0; i < selection_paths.length; i++) {
371 CollectionTreeNode node = (CollectionTreeNode) selection_paths[i].getLastPathComponent();
372 source_files[i] = node.getFile();
373 }
374 Gatherer.f_man.replaceSrcDocWithHtml(source_files); // passing the selected files
375 }
376
377 // Delete
378 else if (source == delete) {
379 CollectionTreeNode[] source_nodes = new CollectionTreeNode[selection_paths.length];
380 for (int i = 0; i < selection_paths.length; i++) {
381 source_nodes[i] = (CollectionTreeNode) selection_paths[i].getLastPathComponent();
382 }
383
384 // Fire a delete action
385 Gatherer.f_man.action(collection_tree, source_nodes, Gatherer.recycle_bin, null);
386 }
387
388 // Meta-audit
389 else if (source == metaaudit) {
390 Gatherer.g_man.showMetaAuditBox();
391 }
392
393 // New folder
394 else if (source == new_folder) {
395 Gatherer.f_man.newFolder(collection_tree, node);
396 }
397
398 // New dummy doc
399 else if (source == new_dummy_doc) {
400 Gatherer.f_man.newDummyDoc(collection_tree, node);
401 }
402
403 // Refresh action to reload folder view
404 else if (source == refresh) { // Refresh collection tree
405 Gatherer.g_man.refreshCollectionTree(DragTree.COLLECTION_CONTENTS_CHANGED);
406 }
407
408 // Open in external program
409 else if (source == open_externally) {
410 Gatherer.f_man.openFileInExternalApplication(node.getFile());
411 }
412
413 // Rename
414 else if (source == rename) {
415 Gatherer.f_man.renameCollectionFile(collection_tree, node);
416 }
417
418 // Replace
419 else if (source == replace) {
420 Gatherer.f_man.replaceCollectionFile(collection_tree, node);
421 }
422 }
423 }
424}
Note: See TracBrowser for help on using the repository browser.