KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ca > directory > jxplorer > tree > SmartPopupTool


1 package com.ca.directory.jxplorer.tree;
2
3 import com.ca.commons.cbutil.CBIntText;
4 import com.ca.commons.cbutil.CBUtility;
5 import com.ca.commons.naming.*;
6 import com.ca.directory.jxplorer.ButtonRegister;
7 import com.ca.directory.jxplorer.JXplorer;
8 import com.ca.directory.jxplorer.event.JXplorerEvent;
9
10 import javax.swing.*;
11 import javax.swing.tree.TreePath JavaDoc;
12 import java.awt.*;
13 import java.awt.datatransfer.Clipboard JavaDoc;
14 import java.awt.datatransfer.StringSelection JavaDoc;
15 import java.awt.event.ActionEvent JavaDoc;
16 import java.awt.event.ActionListener JavaDoc;
17 import java.util.logging.Logger JavaDoc;
18
19
20
21 /**
22  * This is the small popup menu that appears when a manager left-clicks
23  * (or system-dependant-whatever-s) on the display tree, allowing them
24  * to cut/copy/paste/delete/rename tree elements
25  */

26
27 public class SmartPopupTool extends JPopupMenu
28     implements ActionListener JavaDoc
29 {
30     DN cutDN; // DN of node that was *previously* selected to be cut
31
DN copyDN; // DN of node that was *previously* selected to copy
32
DN selectDN; // DN of node grabbed by 'copy DN'
33
boolean newEnabled=true; // whether the 'new' option is on or not
34

35     JMenuItem cut,copy,paste,pasteAlias,delete,rename,search,newEntry,refresh,copydn,bookmark;
36
37     ButtonRegister br = null;
38     SmartTree tree;
39
40     private static Logger JavaDoc log = Logger.getLogger(SmartPopupTool.class.getName());
41
42
43     /**
44      * Constructor initialises the drop down menu and menu items,
45      * and registers 'this'
46      * component as being the listener for all the menu items.
47      * @param owningTree
48      */

49     public SmartPopupTool(SmartTree owningTree)
50     {
51         tree = owningTree;
52
53         String JavaDoc dirImage = JXplorer.getProperty("dir.images");
54         String JavaDoc dirIcons = JXplorer.getProperty("dir.icons");
55
56         add(bookmark = new JMenuItem(CBIntText.get("Add to Bookmarks"), new ImageIcon(dirImage + "plus.gif")));
57         add(search = new JMenuItem(CBIntText.get("Search"), new ImageIcon( dirImage + "find.gif")));
58         add(new JPopupMenu.Separator());
59         add(newEntry = new JMenuItem(CBIntText.get("New"), new ImageIcon( dirImage + "new.gif")));
60         add(copydn = new JMenuItem(CBIntText.get("Copy DN"), new ImageIcon(dirImage + "copy_dn.gif")));
61         add(new JPopupMenu.Separator());
62         add(cut = new JMenuItem(CBIntText.get("Cut Branch"), new ImageIcon( dirImage + "cut.gif")));
63         add(copy = new JMenuItem(CBIntText.get("Copy Branch"), new ImageIcon( dirImage + "copy.gif")));
64         add(paste = new JMenuItem(CBIntText.get("Paste Branch"), new ImageIcon( dirImage + "paste.gif")));
65         add(pasteAlias = new JMenuItem(CBIntText.get("Paste Alias"), new ImageIcon(dirIcons + "alias.gif")));
66         add(new JPopupMenu.Separator());
67         add(delete = new JMenuItem(CBIntText.get("Delete"), new ImageIcon( dirImage + "delete.gif")));
68         add(rename = new JMenuItem(CBIntText.get("Rename"), new ImageIcon( dirImage + "rename.gif")));
69         add(refresh = new JMenuItem(CBIntText.get("Refresh"), new ImageIcon( dirImage + "refresh.gif")));
70
71         bookmark.setToolTipText(CBIntText.get("Bookmark an entry"));
72         bookmark.setAccelerator(KeyStroke.getKeyStroke("B".charAt(0), java.awt.Event.CTRL_MASK, false));
73
74         search.setAccelerator(KeyStroke.getKeyStroke("F".charAt(0), java.awt.Event.CTRL_MASK, false));
75         search.setToolTipText(CBIntText.get("Search for an entry in the directory."));
76
77         cut.setAccelerator(KeyStroke.getKeyStroke("U".charAt(0), java.awt.Event.CTRL_MASK, false));
78         cut.setToolTipText(CBIntText.get("Select a subtree to move."));
79
80         copy.setAccelerator(KeyStroke.getKeyStroke("O".charAt(0), java.awt.Event.CTRL_MASK, false));
81         copy.setToolTipText(CBIntText.get("Select a subtree to copy."));
82
83         paste.setAccelerator(KeyStroke.getKeyStroke("P".charAt(0), java.awt.Event.CTRL_MASK, false));
84         paste.setToolTipText(CBIntText.get("Paste a previously selected subtree."));
85
86         delete.setAccelerator(KeyStroke.getKeyStroke("D".charAt(0), java.awt.Event.CTRL_MASK, false));
87         delete.setToolTipText(CBIntText.get("Delete an entry."));
88
89         rename.setAccelerator(KeyStroke.getKeyStroke("M".charAt(0), java.awt.Event.CTRL_MASK, false));
90         rename.setToolTipText(CBIntText.get("Rename an entry."));
91
92         copydn.setAccelerator(KeyStroke.getKeyStroke("Y".charAt(0), java.awt.Event.CTRL_MASK, false));
93         copydn.setToolTipText(CBIntText.get("Copy the distinguished name of an entry to the clipboard"));
94
95         newEntry.setAccelerator(KeyStroke.getKeyStroke("N".charAt(0), java.awt.Event.CTRL_MASK, false));
96         newEntry.setToolTipText(CBIntText.get("Create a new entry."));
97
98         refresh.setAccelerator(KeyStroke.getKeyStroke("R".charAt(0), java.awt.Event.CTRL_MASK, false));
99         refresh.setToolTipText(CBIntText.get("Refresh an entry."));
100
101         for (int i=0; i<getComponentCount(); i++)
102             if (getComponent(i) instanceof JMenuItem)
103                 ((JMenuItem)getComponent(i)).addActionListener(this);
104
105         setVisible(false);
106         cutDN = null; copyDN = null; //activeDN = null;
107

108         br = JXplorer.getButtonRegister();
109
110         br.registerItem(br.PASTE, paste);
111         br.registerItem(br.PASTE_ALIAS, pasteAlias);
112         br.registerItem(br.COPY, copy);
113         br.registerItem(br.COPY_DN, copydn);
114         br.registerItem(br.CUT, cut);
115         br.registerItem(br.DELETE, delete);
116         br.registerItem(br.NEW, newEntry);
117         br.registerItem(br.RENAME, rename);
118         br.registerItem(br.REFRESH, refresh);
119         br.registerItem(br.BOOKMARKS, bookmark);
120         br.registerItem(br.SEARCH, search);
121
122         br.setItemEnabled(br.PASTE, false);
123         br.setItemEnabled(br.PASTE_ALIAS, false);
124     }
125
126
127
128     /**
129      * This displays the popup tool at the right spot. Some special
130      * magic here allows us to set the state of the popup tool if we want.
131      * @param invoker
132      * @param x
133      * @param y
134      */

135
136     public void show(Component invoker, int x, int y)
137     {
138         SmartTree tree = (SmartTree) invoker;
139         SmartNode node = tree.getSelectedNode();
140
141         boolean modifiable = (node != null && (node.isStructural() == false) && !tree.getName().equalsIgnoreCase("Schema"));
142
143         br.setItemEnabled(br.RENAME, modifiable);
144
145         super.show(invoker, x, y);
146     }
147
148
149
150     /**
151      * Returns the last set active path (e.g. the TreePath corresponding to
152      * the last highlighted tree node).
153      */

154
155     public TreePath JavaDoc getActivePath()
156     {
157         return tree.getSelectionPath();
158     }
159
160
161
162     /**
163      * Returns the most recently selected tree node.
164      */

165
166     public SmartNode getActiveNode()
167     {
168         TreePath JavaDoc path = getActivePath();
169         return (path==null)?null:(SmartNode)path.getLastPathComponent();
170     }
171
172
173
174     /**
175      *
176      * @return
177      */

178
179     public DN getActiveDN()
180     {
181         return tree.getTreeModel().getDNForPath(getActivePath());
182     }
183
184
185
186     /**
187      * This is called externally to popupTreeTool. It highlights
188      * the path, and records the highlighted node's DN for use
189      * by the menu items. This ftn is called from the mouse
190      * listener that kicks off the popupTreeTool, or by @SmartTree.valueChanged.
191      *
192      * @param ActivePath the set of nodes to select.
193      */

194 /*
195     public void setActivePath(TreePath ActivePath)
196     {
197         activePath = ActivePath;
198         activeDN = tree.getTreeModel().getDNForPath(activePath);
199     }
200 */

201
202
203
204     /**
205      * This sets whether the popup tool will show functions that will modify the directory.
206      * @param canModify
207      */

208
209     public void setModifiable(boolean canModify)
210     {
211         if (canModify == false)
212         {
213             br.setItemEnabled(br.CUT, false);
214             br.setItemEnabled(br.COPY, false);
215             br.setItemEnabled(br.DELETE, false);
216             br.setItemEnabled(br.RENAME, false);
217             br.setItemEnabled(br.NEW, false);
218             br.setItemEnabled(br.SEARCH, false);
219             br.setItemEnabled(br.BOOKMARKS, false);
220             br.setItemEnabled(br.PASTE, false);
221             br.setItemEnabled(br.PASTE_ALIAS, false);
222         }
223         else
224         {
225             br.setItemEnabled(br.CUT, true);
226             br.setItemEnabled(br.COPY, true);
227             br.setItemEnabled(br.DELETE, true);
228             br.setItemEnabled(br.RENAME, true);
229             br.setItemEnabled(br.NEW, true);
230             br.setItemEnabled(br.SEARCH, true);
231             br.setItemEnabled(br.BOOKMARKS, true);
232         }
233     }
234
235
236
237     /**
238      *
239      * @param enable
240      */

241
242     public void setNewEntryEnabled(boolean enable)
243     {
244         newEnabled = enable;
245         br.setItemEnabled(br.NEW, newEnabled);
246     }
247
248
249
250     /**
251      * This handles the menu item actions. They rely on
252      * 'activeDN' being set prior to this method being called
253      * (usually by setActivePath() above). Most of the action
254      * handling is simply tossing arguments to the treeDataSource,
255      * and any required tree methods to reflect the changes made.
256      *
257      * @param ev the active event, i.e. the menu item selected
258      */

259
260     public void actionPerformed(ActionEvent JavaDoc ev)
261     {
262         Object JavaDoc event = ev.getSource();
263         setVisible(false);
264         repaint();
265         if (event == cut)
266             cut();
267         else if (event == copy)
268             copy();
269         else if (event == paste)
270             paste();
271         else if (event == pasteAlias)
272             pasteAlias();
273         else if (event == delete)
274             delete();
275         else if (event == rename)
276             rename();
277         else if (event == newEntry)
278             newEntry();
279         else if (event == refresh)
280             refresh();
281         else if (event == copydn)
282             copyDN();
283         else if (event == bookmark)
284             tree.openAddBookmarkDialog(getActiveDN()); //TE: open the bookmark dialog via SmartTree.
285
else if (event == search)
286             tree.openSearch(getActiveDN()); //TE: open the search dialog via SmartTree.
287
else // should never happen...
288
log.warning("Unknown event in popup menu:\n" + ev.toString());
289
290 // repaint();
291
}
292
293 // XXX All this code below needs to be hived off into a separate 'SmartTreeOperations'
294
// XXX class of something...
295

296
297     /**
298      * 'Cuts' a subtree by registering the DN of the cut branch,
299      * which is accessed by the paste ftn. - the @paste ftn then
300      * has responsibility for moving the subtree.
301      */

302
303     public void cut()
304     {
305         DN activeDN = getActiveDN();
306
307         log.fine("Cut "+ activeDN);
308         cutDN = activeDN;
309         copyDN = null;
310         selectDN = null;
311         br.setItemEnabled(br.PASTE, true);
312         br.setItemEnabled(br.PASTE_ALIAS, false);
313     }
314
315
316
317     /**
318      * 'Copies' a subtree by registering the DN of the copied
319      * branch, which is accessed by the paste ftn. - the @paste
320      * ftn then has responsibility for copying the subtree.
321      */

322
323     public void copy()
324     {
325         DN activeDN = getActiveDN();
326         log.fine("Copy "+ activeDN);
327         copyDN = activeDN;
328         cutDN = null;
329         selectDN = null;
330         br.setItemEnabled(br.PASTE, true);
331         br.setItemEnabled(br.PASTE_ALIAS, true);
332     }
333
334
335
336    /**
337     * This checks to see if the 'confirm tree operations' option is on. If it is,
338     * it sticks up an annoying dialog box to ask the user whether they actually want
339     * to do what they just asked to do.
340     * @param operationType the type of operation being performed e.g. delete, copy etc.
341     */

342
343     protected boolean checkAction(String JavaDoc operationType)
344     {
345 // String prop = com.ca.directory.jxplorer.JXplorer.myProperties.getProperty("option.confirmTreeOperations");
346
String JavaDoc prop = JXplorer.getProperty("option.confirmTreeOperations");
347
348         if ("false".equalsIgnoreCase(prop)) // the user has wisely decided not to bother with this mis-feature.
349
return true;
350
351         return (JOptionPane.showConfirmDialog(this, CBIntText.get("The {0} operation will modify the directory - continue?", new String JavaDoc[] {operationType}),
352                     CBIntText.get("Confirm Tree Operation"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE)
353             == JOptionPane.OK_OPTION);
354     }
355
356
357
358     /**
359      * The paste ftn either copies or moves a pre-selected subtree
360      * depending
361      */

362
363     public void paste()
364     {
365         // make sure we're not pasting something into itself...
366
DN activeDN = getActiveDN();
367
368         if ((activeDN==null)||(cutDN == null && copyDN == null)) // should never happen...
369
return; // so ignore it.
370

371         String JavaDoc from = (copyDN==null)?cutDN.toString():copyDN.toString();
372         String JavaDoc to = activeDN.toString();
373         log.fine("pasting: \n" + from + "\n" + to);
374
375         if (to.endsWith(from))
376         {
377             CBUtility.error(this, CBIntText.get("Unable to paste an object into itself!"));
378             return;
379         }
380         if (copyDN != null)
381         {
382             copy(copyDN, activeDN);
383         }
384         else if (cutDN != null)
385         {
386             move(cutDN, activeDN);
387         }
388     }
389
390
391
392    /**
393     * Move the node to another location (performs a cut operation).
394     * Currently this is being used by the drag functionality - the difference
395     * between this method and the move(DN moveFrom, DN moveTo) method is purely
396     * that this method does NOT show a confirmation message even if that option is
397     * set to true by the user.
398     * @param moveFrom the DN of the entry to be moved (or cut).
399     * @param moveTo the new DN of the entry i.e. where it will be cut to.
400     * .
401     */

402     //TE: XXXXXXX A TEMP FIX FOR BUG 2742 - WE STILL NEED A CONFIRMATION DIALOG...THIS IS
403
// JUST A WORK AROUND FOR JX CRASHING WHEN DISPLAYING THE CONFIRMATION DIALOG.
404
public void dragMove(DN moveFrom, DN moveTo)
405     {
406         try
407         {
408             moveTo.addChildRDN(moveFrom.getLowestRDN().toString());
409         }
410         catch (javax.naming.InvalidNameException JavaDoc e)
411         {
412             CBUtility.error(tree, CBIntText.get("Unable to add {0} to {1} due to bad name", new String JavaDoc[] {moveFrom.toString(),moveTo.toString()}),e);
413             return;
414         }
415
416         tree.modifyEntry(new DXEntry(moveFrom), new DXEntry(moveTo));
417
418         cutDN = null;
419         br.setItemEnabled(br.PASTE, false);
420         br.setItemEnabled(br.PASTE_ALIAS, false);
421     }
422
423
424
425    /**
426     * Move the node to another location (performs a cut operation).
427     * @param moveFrom the DN of the entry to be moved (or cut).
428     * @param moveTo the new DN of the entry i.e. where it will be cut to.
429     */

430
431     public void move(DN moveFrom, DN moveTo)
432     {
433         // 'move'ing a tree means placing the old tree *under*
434
// the newly selected tree... hence deepen 'activeDN' by
435
// one new level. (i.e. ou=eng,o=uni,c=au moved to o=biz,c=au
436
// requires activeDN extended to ou=eng,o=biz,c=au before move
437

438         if (checkAction("cut") == false)
439            return;
440
441         try
442         {
443             moveTo.addChildRDN(moveFrom.getLowestRDN().toString());
444         }
445         catch (javax.naming.InvalidNameException JavaDoc e)
446         {
447             CBUtility.error(tree, CBIntText.get("Unable to add {0} to {1} due to bad name", new String JavaDoc[] {moveFrom.toString(),moveTo.toString()}),e);
448             return;
449         }
450
451         tree.modifyEntry(new DXEntry(moveFrom), new DXEntry(moveTo));
452
453         cutDN = null;
454         br.setItemEnabled(br.PASTE, false);
455         br.setItemEnabled(br.PASTE_ALIAS, false);
456     }
457
458
459
460    /**
461     * Copys (in the directory) the selected DN to the new
462     * destination. The copied entry/subtree is placed *under*
463     * the destination node.
464     * Currently this is being used by the drag functionality - the difference
465     * between this method and the copy(DN copyFrom, DN copyTo) method is purely
466     * that this method does NOT show a confirmation message even if that option is
467     * set to true by the user.
468     * @param copyFrom the DN of an entry or subtree apex to copy entries from
469     * @param copyTo the location to copy to.
470     * .
471     */

472     //TE: XXXXXXX A TEMP FIX FOR BUG 2742 - WE STILL NEED A CONFIRMATION DIALOG...THIS IS
473
// JUST A WORK AROUND FOR JX CRASHING WHEN DISPLAYING THE CONFIRMATION DIALOG.
474
public void dragCopy(DN copyFrom, DN copyTo)
475     {
476         tree.copyTree(copyFrom, copyTo);
477     }
478
479
480
481     /**
482      * Copys (in the directory) the selected Dn to the new
483      * destination. The copied entry/subtree is placed *under*
484      * the destination node.
485      * @param copyFrom the DN of an entry or subtree apex to copy entries from
486      * @param copyTo the location to copy to.
487      */

488
489     public void copy(DN copyFrom, DN copyTo)
490     {
491         if (checkAction("paste") == false)
492             return;
493
494         tree.copyTree(copyFrom, copyTo);
495     }
496
497
498     /**
499      * Deletes the currently <i>selected</i> entry.
500      */

501     public void delete()
502     {
503         DN activeDN = getActiveDN();
504
505         // If a delete is performed with a null DN, the whole DIT is deleted. Check for a null DN...
506
if(activeDN == null || activeDN.isEmpty())
507         {
508             log.warning("An invalid DN was requested to be deleted: " + activeDN);
509
510             JOptionPane.showMessageDialog(this, CBIntText.get("Please select a valid entry to delete."),
511                         CBIntText.get("No Entry Selected"), JOptionPane.WARNING_MESSAGE);
512
513             return;
514         }
515
516         if (checkAction("delete") == false)
517             return;
518
519         log.fine("deleting " + activeDN);
520
521         tree.modifyEntry(new DXEntry(activeDN), null);
522         br.setItemEnabled(br.PASTE_ALIAS, false);
523
524         tree.clearEntry(); //TE: display a null entry.
525
}
526
527
528
529     /**
530      * Starts the tree cell editor on the currently <i>selected</i> entry.
531      */

532
533     public void rename()
534     {
535         if (checkAction("rename") == false) return;
536
537         tree.getTree().startEditingAtPath(getActivePath()); // renameSubTree called by the TreeCellListener
538
br.setItemEnabled(br.PASTE_ALIAS, false);
539     }
540
541
542
543     /**
544      * Uses the tree to start the process of creating a new entry.
545      */

546
547     public void newEntry()
548     {
549         if (newEnabled==false)
550         {
551             CBUtility.warning(this,CBIntText.get("Browser unable to add new entries using ldap 2 connection"), CBIntText.get("reduced funcitonality in ldap 2"));
552         }
553         else
554         {
555             setVisible(false);
556             repaint();
557             tree.makeNewEntry(getActiveDN());
558         }
559     }
560
561     /**
562      * Creates an alias of the currently copied or copyDN-ed entry
563      */

564
565     public void pasteAlias()
566     {
567         if (checkAction("paste alias") == false)
568             return;
569
570         DN aliasedObject = selectDN;
571         if (aliasedObject == null)
572             aliasedObject = copyDN;
573         if (aliasedObject == null)
574         {
575             log.warning("no DN selected for aliasing.");
576             br.setItemEnabled(br.PASTE_ALIAS, false);
577             return;
578         }
579
580         DN newAlias = new DN(getActiveDN());
581         RDN newAliasName = aliasedObject.getLowestRDN();
582         newAlias.add(newAliasName);
583
584         DXEntry alias = new DXEntry(newAlias);
585         DXAttribute oc = new DXAttribute("objectClass", "top");
586         oc.add("alias");
587         alias.put(oc);
588         alias.put(new DXAttribute("aliasedObjectName", aliasedObject.toString()));
589         alias.put(new DXAttribute(newAliasName.getAtt(), newAliasName.getRawVal()));
590
591         tree.modifyEntry(null, alias);
592     }
593
594     /**
595      * Reads the directory to refresh the currently selected entry's data
596      * and it's immediate children.
597      */

598
599     public void refresh()
600     {
601         tree.refresh(getActiveDN());
602     }
603
604     /**
605      * Copies a previously selected entry (and it's children) to
606      * the new position, <i>under</i> the current selection.
607      */

608
609     public void copyDN()
610     {
611         selectDN = new DN(getActiveDN());
612         StringSelection JavaDoc ss = new StringSelection JavaDoc(selectDN.toString());
613         Clipboard JavaDoc clip = Toolkit.getDefaultToolkit().getSystemClipboard();
614         clip.setContents(ss,ss);
615         tree.fireJXplorerEvent(new JXplorerEvent(this, JXplorerEvent.EventType.DNSELECTED, selectDN.toString()));
616
617         if(!tree.getName().equalsIgnoreCase("Schema"))
618             br.setItemEnabled(br.PASTE_ALIAS, true);
619         br.setItemEnabled(br.PASTE, false);
620     }
621 }
Popular Tags