KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > aspects > gui > swing > Tree


1 /*
2   Copyright (C) 2003-2003 Renaud Pawlak <renaud@aopsys.com>,
3                           Laurent Martelli <laurent@aopsys.com>
4   
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU Lesser General Public License as
7   published by the Free Software Foundation; either version 2 of the
8   License, or (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with this program; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18   USA */

19
20 package org.objectweb.jac.aspects.gui.swing;
21
22
23 import java.awt.BorderLayout JavaDoc;
24 import java.awt.Component JavaDoc;
25 import java.awt.Dimension JavaDoc;
26 import java.awt.datatransfer.*;
27 import java.awt.dnd.*;
28 import java.awt.event.ActionEvent JavaDoc;
29 import java.awt.event.ActionListener JavaDoc;
30 import java.awt.event.KeyEvent JavaDoc;
31 import java.awt.event.KeyListener JavaDoc;
32 import java.awt.event.MouseEvent JavaDoc;
33 import java.awt.event.MouseListener JavaDoc;
34 import java.util.Arrays JavaDoc;
35 import java.util.Enumeration JavaDoc;
36 import java.util.List JavaDoc;
37 import javax.swing.Icon JavaDoc;
38 import javax.swing.ImageIcon JavaDoc;
39 import javax.swing.JButton JavaDoc;
40 import javax.swing.JPanel JavaDoc;
41 import javax.swing.JScrollPane JavaDoc;
42 import javax.swing.JTree JavaDoc;
43 import javax.swing.ToolTipManager JavaDoc;
44 import javax.swing.event.TreeExpansionEvent JavaDoc;
45 import javax.swing.event.TreeExpansionListener JavaDoc;
46 import javax.swing.event.TreeSelectionEvent JavaDoc;
47 import javax.swing.event.TreeSelectionListener JavaDoc;
48 import javax.swing.tree.DefaultTreeCellRenderer JavaDoc;
49 import javax.swing.tree.TreeNode JavaDoc;
50 import javax.swing.tree.TreePath JavaDoc;
51 import org.apache.log4j.Logger;
52 import org.objectweb.jac.aspects.gui.*;
53 import org.objectweb.jac.aspects.gui.Transfer;
54 import org.objectweb.jac.core.Collaboration;
55 import org.objectweb.jac.core.Wrappee;
56 import org.objectweb.jac.core.rtti.CollectionItem;
57 import org.objectweb.jac.core.rtti.FieldItem;
58 import org.objectweb.jac.core.rtti.MethodItem;
59
60 /**
61  * This class defines a Swing component tree view for objects that are
62  * related to a root object through relations or collections.
63  *
64  * @see GuiAC */

65
66 public class Tree extends AbstractView
67     implements View, TreeSelectionListener JavaDoc, MouseListener JavaDoc,
68                TreeExpansionListener JavaDoc, TreeListener, KeyListener JavaDoc,
69                DragGestureListener, DragSourceListener, DropTargetListener
70 {
71     static Logger logger = Logger.getLogger("gui.treeview");
72
73     JTree JavaDoc tree;
74     TreeModel model;
75     // String pathDef = null;
76
boolean showRelations = true;
77
78     JButton JavaDoc viewButton = null;
79     JButton JavaDoc newButton = null;
80     JButton JavaDoc removeButton = null;
81
82     RootNode rootNode = null;
83
84     /**
85      * Builds a new tree view.
86      *
87      * @param pathDef designate root objects of the tree
88      * @param showRelations wether to build a node for relation items
89      */

90     public Tree(ViewFactory factory, DisplayContext context,
91                 String JavaDoc pathDef, boolean showRelations ) {
92         super(factory,context);
93
94         this.showRelations = showRelations;
95
96         setLayout(new BorderLayout JavaDoc());
97
98         tree = new JTree JavaDoc();
99
100         DragSource dragSource = DragSource.getDefaultDragSource();
101         // creating the recognizer is all that's necessary - it
102
// does not need to be manipulated after creation
103
dragSource.createDefaultDragGestureRecognizer(
104             tree, // component where drag originates
105
DnDConstants.ACTION_COPY_OR_MOVE, // actions
106
this); // drag gesture listener
107

108         JScrollPane JavaDoc upperCont = new JScrollPane JavaDoc(tree);
109         tree.addTreeExpansionListener(this);
110         JPanel JavaDoc downCont = new JPanel JavaDoc();
111
112         tree.putClientProperty("JTree.lineStyle", "Angled");
113         ToolTipManager.sharedInstance().registerComponent(tree);
114         tree.setRootVisible(false);
115         tree.addTreeSelectionListener( this );
116
117         rootNode = new RootNode();
118         model = new TreeModel(rootNode, pathDef, showRelations);
119         tree.setModel(model);
120         tree.setCellRenderer(new TreeNodeRenderer());
121         tree.addMouseListener(this);
122         tree.addKeyListener(this);
123         model.addTreeListener(this);
124
125         // add, remove and view buttons
126
viewButton = createButton("view_icon","View",new openHandler());
127         downCont.add(viewButton);
128
129       
130         newButton = createButton("new_icon","Add",new addHandler());
131         downCont.add(newButton);
132
133         removeButton = createButton(
134             "remove_icon","Remove",
135             new ActionListener JavaDoc() {
136                     public void actionPerformed(ActionEvent JavaDoc event) {
137                         doDelete(false);
138                     }
139                 }
140         );
141
142         downCont.add(removeButton);
143
144         add(upperCont, BorderLayout.CENTER);
145         add(downCont, BorderLayout.SOUTH);
146
147         new DropTarget(tree, // component
148
DnDConstants.ACTION_COPY_OR_MOVE, // actions
149
this); // DropTargetListener
150

151         expandRoot();
152     }
153
154     // DND interfaces
155
public void dragGestureRecognized(DragGestureEvent e) {
156         loggerDnd.debug("drag gesture detected");
157         // drag anything ...
158

159         TreePath JavaDoc tp = tree.getPathForLocation(
160             (int)e.getDragOrigin().getX(), (int)e.getDragOrigin().getY() );
161         if (tp != null) {
162             AbstractNode node=(AbstractNode) tp.getLastPathComponent();
163             Object JavaDoc o = node.getUserObject();
164             if(o instanceof Wrappee) {
165                 node=(AbstractNode)node.getParent();
166                 Object JavaDoc parent = node.getUserObject();
167                 if(parent != null && (parent instanceof FieldItem)) {
168                     node=(AbstractNode)node.getParent();
169                     parent = node.getUserObject();
170                 }
171                 Wrappee[] toTransfer;
172                 if(parent instanceof Wrappee) {
173                     toTransfer=new Wrappee[] {(Wrappee)o,(Wrappee)parent};
174                 } else {
175                     toTransfer=new Wrappee[] {(Wrappee)o,null};
176                 }
177                 loggerDnd.debug("to transfer: "+Arrays.asList(toTransfer));
178                 e.startDrag(
179                     null,//DragSource.DefaultCopyDrop, // cursor
180
Transfer.getJACTransfer(toTransfer),
181                     this); // drag source listener
182
}
183         }
184     }
185     public void dragDropEnd(DragSourceDropEvent e) {}
186     public void dragEnter(DragSourceDragEvent e) {}
187     public void dragExit(DragSourceEvent e) {}
188     public void dragOver(DragSourceDragEvent e) {}
189     public void dropActionChanged(DragSourceDragEvent e) {}
190
191     public void drop(DropTargetDropEvent e) {
192         try {
193             loggerDnd.debug("drop event");
194             Transferable tr = e.getTransferable();
195             TreePath JavaDoc tp = tree.getPathForLocation(
196                 (int)e.getLocation().getX(), (int)e.getLocation().getY() );
197             if(tp!=null) {
198                 List transfered=Transfer.getTransferedWrappees(tr);
199                 Object JavaDoc droppedObject=transfered.get(0);
200                 Object JavaDoc source=transfered.get(1);
201                 Object JavaDoc target=((AbstractNode) tp.getLastPathComponent()).getUserObject();
202                 loggerDnd.debug("target="+target+", droppedObject="+
203                                 droppedObject+", source="+source);
204                 if(droppedObject==null || target==null ||
205                    (!(target instanceof Wrappee)) ) return;
206                 EventHandler.get().onDropObject(getContext(),target,droppedObject,source,false);
207             }
208         } catch(Exception JavaDoc ex) {
209             ex.printStackTrace();
210         }
211     }
212     public void dragEnter(DropTargetDragEvent e) {}
213     public void dragExit(DropTargetEvent e) {}
214     public void dragOver(DropTargetDragEvent e) {}
215     public void dropActionChanged(DropTargetDragEvent e) {}
216
217     // end of DND interfaces
218

219     /**
220      * Expands nodes linked to the tree root. Useful because it is not
221      * automatically done and nodes or expand buttons are not displayed
222      * at the beginning (you can't open children).
223      */

224    
225     public void expandRoot()
226     {
227         Object JavaDoc root = model.getRoot();
228         int rootCount = model.getChildCount(root);
229         for (int i=0; i<rootCount; i++)
230         {
231             Object JavaDoc child = model.getChild(root, i);
232             TreePath JavaDoc path = new TreePath JavaDoc(model.getPathToRoot((TreeNode JavaDoc) child));
233             logger.debug("Expanding path "+path);
234             tree.expandPath(path);
235         }
236     }
237
238     /**
239      * Create a disabled button
240      * @param inconName resource name of the icon
241      * @param text text of the icon, which is used as a tooltip if iconName!=null
242      * @param listener an ActionListener for the button
243      * @return a new button
244      */

245     JButton JavaDoc createButton(String JavaDoc iconName, String JavaDoc text, ActionListener JavaDoc listener) {
246         ImageIcon JavaDoc icon = ResourceManager.getIconResource(iconName);
247         JButton JavaDoc button;
248         if (icon==null)
249             button = new JButton JavaDoc (text);
250         else {
251             button = new JButton JavaDoc(icon);
252             button.setToolTipText(text);
253         }
254         button.addActionListener(listener);
255         button.setEnabled(false);
256         return button;
257     }
258
259     // interface TreeView
260

261     public void close(boolean validate) {
262         model.unregisterEvents();
263     }
264
265     void selectObject(AbstractNode root,Object JavaDoc toSelect) {
266         Enumeration JavaDoc children=root.children();
267         while(children.hasMoreElements()) {
268             AbstractNode node = (AbstractNode)children.nextElement();
269             if( node.getUserObject()==toSelect ) {
270                 AbstractNode parent = (AbstractNode)node.getParent();
271                 while (parent!=null) {
272                     tree.expandPath(new TreePath JavaDoc(parent.getPath()));
273                     parent = (AbstractNode)parent.getParent();
274                 }
275                 tree.expandPath(new TreePath JavaDoc(node.getPath()));
276                 tree.addSelectionPath(new TreePath JavaDoc(node.getPath()));
277             }
278             selectObject(node,toSelect);
279         }
280     }
281
282     public void treeCollapsed(TreeExpansionEvent JavaDoc event) {
283         loggerEvents.debug("treeCollapsed "+event.getPath());
284     }
285
286     public void treeExpanded(TreeExpansionEvent JavaDoc event) {
287         loggerEvents.debug("treeExpanded "+event.getPath());
288         Object JavaDoc node = (AbstractNode)event.getPath().getLastPathComponent();
289         if (node instanceof ObjectNode) {
290             ((ObjectNode)node).updateChildren();
291         }
292     }
293
294     /**
295      * Handles the tree view selection changes.
296      */

297     public void valueChanged(TreeSelectionEvent JavaDoc event) {
298         loggerEvents.debug("valueChanged "+event.getSource().getClass().getName());
299         AbstractNode node = (AbstractNode)
300             tree.getLastSelectedPathComponent();
301         if (node == null) {
302             viewButton.setEnabled(false);
303             removeButton.setEnabled(false);
304         } else {
305             Object JavaDoc selected = node.getUserObject();
306             if (selected instanceof CollectionItem) {
307                 loggerEvents.debug("selected the collection "+
308                                    ((CollectionItem)selected).getName());
309                 viewButton.setEnabled(false);
310                 newButton.setEnabled(true);
311                 removeButton.setEnabled(doDelete(true));
312             } else {
313                 loggerEvents.debug("selected a wrappee "+selected);
314                 viewButton.setEnabled(selected!=null);
315                 newButton.setEnabled(false);
316                 removeButton.setEnabled(doDelete(true));
317                 EventHandler.get().onNodeSelection(context,node,false);
318             }
319         }
320     }
321
322     // MouseListener interface
323

324     /** Do nothing. */
325     public void mouseClicked(MouseEvent JavaDoc me){}
326
327     /**
328      * Shows a popup if needed.
329      *
330      * @param e mouse event descriptor */

331
332     public void mousePressed(MouseEvent JavaDoc e) {
333         maybeShowPopup(e);
334     }
335
336     /**
337      * Closes a popup if needed.
338      *
339      * @param e mouse event descriptor */

340
341     public void mouseReleased(MouseEvent JavaDoc e) {
342         maybeShowPopup(e);
343     }
344
345     /** Do nothing. */
346     public void mouseExited(MouseEvent JavaDoc me){}
347     /** Do nothing. */
348     public void mouseEntered(MouseEvent JavaDoc me){}
349
350     private void maybeShowPopup(MouseEvent JavaDoc e) {
351         loggerEvents.debug("maybeShowPopup: "+e.getClass().getName());
352         TreePath JavaDoc tp = tree.getPathForLocation( e.getX(), e.getY() );
353         if (tp != null) {
354             Object JavaDoc o = ((AbstractNode) tp.getLastPathComponent()).getUserObject();
355             if (e.isPopupTrigger()) {
356                 //tree.setSelectionPath(tp);
357
if (o instanceof Wrappee)
358                     SwingEvents.showObjectMenu(context, o, e);
359             }
360         }
361     }
362
363     // KeyListener interface
364

365     public void keyTyped(KeyEvent JavaDoc event) {}
366
367     public void keyPressed(KeyEvent JavaDoc event) {
368         System.out.println("keyPressed "+event);
369     }
370
371     public void keyReleased(KeyEvent JavaDoc event) {
372         if (event.getKeyCode()==KeyEvent.VK_DELETE) {
373             doDelete(false);
374         }
375     }
376
377     public void setSelection(TreePath JavaDoc selection) {
378         tree.setSelectionPath(selection);
379     }
380
381     /**
382      * Handles "open" actions
383      */

384     class openHandler implements ActionListener JavaDoc {
385         public void actionPerformed(ActionEvent JavaDoc event) {
386             loggerEvents.debug("action performed: OPEN");
387             setContext();
388             //TreePath anchorPath = tree.getAnchorSelectionPath();
389
TreePath JavaDoc anchorPath = tree.getSelectionPath();
390             if (anchorPath!=null) {
391                 AbstractNode node = (AbstractNode)anchorPath.getLastPathComponent();
392                 AbstractNode parentNode = (AbstractNode)node.getParent();
393                 Collaboration.get().addAttribute(
394                     "Session.sid",
395                     "Swing"+org.objectweb.jac.core.dist.Distd.getLocalContainerName() );
396                 
397                 if (node instanceof ObjectNode) {
398                     ObjectNode objectNode = (ObjectNode)node;
399                     EventHandler.get().onSelection(
400                         context,objectNode.getRelation(),objectNode.getUserObject(),
401                         null,null,true);
402                 }
403             }
404         }
405     }
406
407     /**
408      * Handles "add" actions
409      */

410     class addHandler implements ActionListener JavaDoc {
411         public void actionPerformed(ActionEvent JavaDoc event) {
412             loggerEvents.debug("action performed: ADD");
413             setContext();
414             AbstractNode node = (AbstractNode)tree
415                 .getAnchorSelectionPath().getLastPathComponent();
416             AbstractNode parentNode = (AbstractNode)node.getParent();
417             Collaboration.get().addAttribute(
418                 "Session.sid", "Swing"+org.objectweb.jac.core.dist.Distd.getLocalContainerName() );
419
420             Object JavaDoc o = node.getUserObject();
421             if( o instanceof CollectionItem ) {
422                 if( parentNode != null ) {
423                     try {
424                         MethodItem[] addingMethods = ((CollectionItem)o).getAddingMethods();
425                         if( addingMethods != null && addingMethods.length > 0 ) {
426                             logger.debug("invoking "+addingMethods[0]+" on "+
427                                       parentNode.getUserObject());
428                             if (((CollectionItem)o).getAttribute(GuiAC.AUTO_CREATE)!=null) {
429                                 logger.debug("auto creation asked");
430                                 Collaboration.get().addAttribute(
431                                     GuiAC.AUTO_CREATE, addingMethods[0].getParameterTypes()[0]);
432                             }
433                             Collaboration.get().addAttribute(
434                                 GuiAC.ASK_FOR_PARAMETERS, addingMethods[0]);
435                             Collaboration.get().addAttribute(
436                                 GuiAC.DISPLAY_CONTEXT, context);
437                             addingMethods[0].invoke(
438                                 parentNode.getUserObject(),
439                                 new Object JavaDoc[addingMethods[0].getParameterTypes().length]);
440                         }
441                     } catch( Exception JavaDoc e ) {
442                         e.printStackTrace();
443                     }
444                 }
445             }
446         }
447     }
448
449     /**
450      * Delete selected objects.
451      *
452      * @param softRun if true, will not actually call delete, but just
453      * return if the user is allowed to see a delete button.
454      * @return true if the user is allowed to see a delete button for
455      * all of the selected objects.
456      */

457     protected boolean doDelete(boolean softRun) {
458         setContext();
459
460         TreePath JavaDoc[] selectionPaths = tree.getSelectionPaths();
461         if (selectionPaths==null)
462             return false;
463         boolean result = true;
464         for (int i=0; i<selectionPaths.length; i++) {
465             loggerEvents.debug("selectionPath = "+selectionPaths[i]);
466             AbstractNode node =
467                 (AbstractNode)selectionPaths[i].getLastPathComponent();
468             AbstractNode parentNode =
469                 (AbstractNode)node.getParent();
470             Object JavaDoc selectedObject = node.getUserObject();
471             if (selectedObject instanceof CollectionItem) {
472                 CollectionItem collection = (CollectionItem)selectedObject;
473                 // If the selected node is a collection node,
474
// interactively invoke the remove method
475
if (parentNode != null &&
476                     GuiAC.isRemovable(parentNode.getUserObject(),collection)) {
477                     if (!softRun) {
478                         EventHandler.get().onRemoveFromCollection(
479                             context,
480                             new RemoveEvent(
481                                 this,
482                                 parentNode.getUserObject(),
483                                 (CollectionItem)selectedObject,
484                                 null),
485                             false);
486                     } else {
487                         result = false;
488                     }
489                 }
490             } else if (node instanceof ObjectNode &&
491                        ((ObjectNode)node).getRelation() instanceof CollectionItem) {
492                 loggerEvents.debug("node = "+node+"; parentNode="+parentNode);
493                 FieldItem coll = ((ObjectNode)node).getRelation();
494                 if (coll instanceof CollectionItem &&
495                     GuiAC.isRemovable(((ObjectNode)node).getSubstance(),
496                                       (CollectionItem)coll))
497                 {
498                     if (!softRun) {
499                         Collaboration.get().addAttribute(GuiAC.REMOVED_NODE,node);
500                         try {
501                             EventHandler.get().onRemoveFromCollection(
502                                 context,
503                                 new RemoveEvent(
504                                     this,
505                                     ((ObjectNode)node).getSubstance(),
506                                     (CollectionItem)coll,
507                                     selectedObject),
508                                 false);
509                         } finally {
510                             Collaboration.get().removeAttribute(GuiAC.REMOVED_NODE);
511                         }
512                     }
513                 } else {
514                     result = false;
515                 }
516             } else {
517                 result = false;
518             }
519         }
520         return result;
521     }
522
523     static class TreeNodeRenderer extends DefaultTreeCellRenderer JavaDoc {
524       
525         public TreeNodeRenderer() {}
526       
527         public Component JavaDoc getTreeCellRendererComponent(JTree JavaDoc tree,
528                                                       Object JavaDoc value,
529                                                       boolean sel,
530                                                       boolean expanded,
531                                                       boolean leaf,
532                                                       int row,
533                                                       boolean hasFocus) {
534          
535             this.hasFocus = hasFocus;
536             AbstractNode node = (AbstractNode)value;
537             setText(node.getText());
538             setToolTipText(node.getToolTip());
539       
540             if(sel)
541                 setForeground(getTextSelectionColor());
542             else
543                 setForeground(getTextNonSelectionColor());
544             // There needs to be a way to specify disabled icons.
545
if (!tree.isEnabled()) {
546                 setEnabled(false);
547                 if (leaf) {
548                     setDisabledIcon(getLeafIcon());
549                 } else if (expanded) {
550                     setDisabledIcon(getOpenIcon());
551                 } else {
552                     setDisabledIcon(getClosedIcon());
553                 }
554             } else {
555                 setEnabled(true);
556                 setIcon(ResourceManager.getIcon(node.getIcon()));
557             }
558             setComponentOrientation(tree.getComponentOrientation());
559             selected = sel;
560
561             return this;
562         }
563
564         public Dimension JavaDoc getPreferredSize() {
565             Dimension JavaDoc dim = super.getPreferredSize();
566             Icon JavaDoc icon = getIcon();
567             if (icon!=null) {
568                 if (icon.getIconHeight()+2>dim.getHeight())
569                     dim.setSize((int)dim.getWidth(), getIcon().getIconHeight()+2);
570             }
571             return dim;
572         }
573
574     }
575 }
576
Popular Tags