source: other-projects/FileTransfer-WebSocketPair/testGXTWithGreenstone/src/org/greenstone/gatherer/collection/CollectionTree.java@ 33053

Last change on this file since 33053 was 33053, checked in by ak19, 5 years ago

I still had some stuff of Nathan Kelly's (FileTransfer-WebSocketPair) sitting on my USB. Had already commited the Themes folder at the time, 2 years back. Not sure if he wanted this additional folder commited. But I didn't want to delete it and decided it will be better off on SVN. When we use his project, if we find we didn't need this test folder, we can remove it from svn then.

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