View Javadoc
1 /*** 2 * ClassDepView.java 3 * 4 * Project: Dependency Tool 5 * 6 * WHEN WHO WHAT 7 * 06.06.2003 pko initial public release 8 * 14.01.2003 pko modification 9 * 22.07.2002 ctr modification 10 * 18.06.2002 ctr creation 11 * 12 * Copyright 2003 ELCA Informatique SA 13 * Av. de la Harpe 22-24, 1000 Lausanne 13, Switzerland 14 * www.elca.ch 15 * 16 * This library is free software; you can redistribute it and/or 17 * modify it under the terms of the GNU Lesser General Public License 18 * as published by the Free Software Foundation; either version 2.1 of 19 * the License, or (at your option) any later version. 20 * 21 * This library is distributed in the hope that it will be useful, but 22 * WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 * Lesser General Public License for more details. 25 * 26 * You should have received a copy of the GNU Lesser General Public 27 * License along with this library; if not, write to the Free Software 28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 29 * USA 30 */ 31 32 package ch.elca.dependency.view; 33 34 import att.grappa.*; 35 import ch.elca.dependency.core.DependencyModel; 36 import ch.elca.dependency.core.classinfo.ClassInfo; 37 import ch.elca.dependency.util.IconGrabber; 38 39 import java.awt.*; 40 import java.awt.event.*; 41 import java.util.*; 42 import javax.swing.*; 43 import javax.swing.event.*; 44 import javax.swing.tree.*; 45 46 import org.apache.log4j.Logger; 47 import info.clearthought.layout.TableLayout; 48 49 /*** 50 * Tree with class dependencies. 51 * 52 * @see ch.elca.dependency.view.View 53 * 54 * @author Christoph Trutmann 55 * @version 1.0-beta 56 */ 57 public class ClassDepView extends View { 58 59 //****************************************************************************************/ 60 // static fields 61 //****************************************************************************************/ 62 63 /*** 64 * Log4j Logger. 65 */ 66 private static final Logger LOG = Logger.getLogger(ClassDepView.class); 67 68 /*** 69 * Title used for this Frame. 70 */ 71 private final static String FRAME_TITLE = "Class Dependency View"; 72 73 //****************************************************************************************/ 74 // instance fields 75 //****************************************************************************************/ 76 77 /*** 78 * <code>ScrollPane</code> holding the tree. Supports add and 79 * remove for changing the tree. 80 */ 81 private JScrollPane m_treeView; 82 83 /*** 84 * Tree holding the class 'uses' dependencies. 85 */ 86 private JTree m_usesTree; 87 88 /*** 89 * Root of the 'uses' tree. 90 */ 91 private MyTreeNode m_usesTreeRoot; 92 93 /*** 94 * Tree holding the class 'is used' dependencies. 95 */ 96 private JTree m_isUsedTree; 97 98 /*** 99 * Root of the 'is used' tree. 100 */ 101 private MyTreeNode m_isUsedTreeRoot; 102 103 /*** 104 * Flag specifying whether the 'uses' or the 'is used' 105 * dependencies are shown. 106 */ 107 private boolean m_uses = true; 108 109 /*** 110 * HashMap containing all the <code>ClassInfo</code> objects of this 111 * project. The key is the full qualified class name. 112 */ 113 private HashMap m_classInfos; 114 115 /*** 116 * Reference to the raw graph. 117 */ 118 private Graph m_graph; 119 120 /*** 121 * Label is displayed when no package is selected. 122 */ 123 private JLabel m_emptyLabel = new JLabel(" Please select a package..."); 124 125 /*** 126 * Map containing the package dependencies. This is used for 127 * checking if a package is intern or extern of the project. 128 */ 129 private HashMap m_packDepend; 130 131 /*** 132 * Creates a new <code>ClassDepView</code> instance. 133 * 134 * @param dependencyModel a <code>DependencyModel</code> value 135 */ 136 public ClassDepView(DependencyModel dependencyModel) { 137 super(dependencyModel, FRAME_TITLE); 138 setDefaultBounds(new Rectangle(165, 564, 330, 297)); 139 recallConfig(); 140 } 141 142 protected void internalInitData() { 143 144 // create the HashMap with all the ClassInfo objects 145 // 146 m_classInfos = new HashMap(); 147 Iterator infoIter = m_dependencyModel.getRawClassInfos().values().iterator(); 148 while ( infoIter.hasNext() ) { 149 ListIterator infoListIter = ((ArrayList)infoIter.next()).listIterator(); 150 while ( infoListIter.hasNext() ) { 151 ClassInfo infoTmp = (ClassInfo)infoListIter.next(); 152 m_classInfos.put(infoTmp.getFullName(), infoTmp); 153 } 154 } 155 156 m_graph = m_dependencyModel.getRawGraph(); 157 m_packDepend = m_dependencyModel.getPackDepend(); 158 } 159 160 /*** 161 * Init this view. 162 */ 163 public void initView(){ 164 165 // create the MenuBar 166 // 167 final JMenuBar menuBar = new JMenuBar(); 168 setJMenuBar(menuBar); 169 170 // build the menu for the dependency direction 171 // 172 JMenu dirMenu = new JMenu("Dependency Direction"); 173 dirMenu.setMnemonic(KeyEvent.VK_D); 174 menuBar.add(dirMenu); 175 176 // button group for the checkboxes 177 // 178 ButtonGroup group = new ButtonGroup(); 179 180 // uses direction MenuItem 181 // 182 JRadioButtonMenuItem usesRadioItem = new JRadioButtonMenuItem("Uses"); 183 usesRadioItem.setSelected(true); 184 usesRadioItem.setMnemonic(KeyEvent.VK_U); 185 group.add(usesRadioItem); 186 usesRadioItem.addActionListener(new ActionListener() { 187 public void actionPerformed(ActionEvent e) { 188 LOG.info("Change tree to 'uses'..."); 189 m_uses = true; 190 changeTreeDepend(); 191 } 192 }); 193 dirMenu.add(usesRadioItem); 194 195 // is used direction MenuItem 196 // 197 JRadioButtonMenuItem isUsedRadioItem 198 = new JRadioButtonMenuItem("Is used"); 199 isUsedRadioItem.setMnemonic(KeyEvent.VK_I); 200 group.add(isUsedRadioItem); 201 isUsedRadioItem.addActionListener(new ActionListener() { 202 public void actionPerformed(ActionEvent e){ 203 LOG.info("Change tree to 'is uses'..."); 204 m_uses = false; 205 changeTreeDepend(); 206 } 207 }); 208 dirMenu.add(isUsedRadioItem); 209 210 // build the menu for selecting something 211 // 212 JMenu selectMenu = new JMenu("Select"); 213 selectMenu.setMnemonic(KeyEvent.VK_S); 214 menuBar.add(selectMenu); 215 216 // build the menu item for selecting a package 217 // 218 JMenuItem packItem = new JMenuItem("Select package", KeyEvent.VK_P); 219 packItem.addActionListener(new ActionListener() { 220 public void actionPerformed(ActionEvent e) { 221 LOG.info("Select a new package for the views."); 222 selectNewPackage(); 223 } 224 }); 225 selectMenu.add(packItem); 226 227 // configure TableLayout 228 // 229 double border = 10; 230 double fill = TableLayout.FILL; 231 double size[][] = 232 {{border, fill, border}, // Columns 233 {border, fill, border}}; // Rows 234 235 this.getContentPane().setLayout(new TableLayout(size)); 236 237 m_treeView = new JScrollPane(m_emptyLabel); 238 getContentPane().add(m_treeView, "1, 1, F, F"); 239 setBackground(menuBar.getBackground()); 240 241 setVisible(true); 242 validate(); 243 244 } 245 246 /*** 247 * Helper method for constructing the two trees. 248 * 249 * @param root Root node of this tree. 250 * @return Tree with the appropriate parameters. 251 */ 252 private JTree constructTree(MyTreeNode root, String mode){ 253 JTree tree = new JTree(root); 254 // only one node can be selected at the same time 255 tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); 256 tree.addTreeSelectionListener(new MyTreeSelectionListener()); 257 tree.addTreeExpansionListener(new MyTreeExpansionListener(mode, this)); 258 // determine the style of the table 259 tree.putClientProperty("JTree.lineStyle", "Angled"); 260 tree.setCellRenderer(new MyRenderer()); 261 return tree; 262 } 263 264 /*** 265 * Displays the <code>OverView</code> after the data has changed. 266 * This mehtod is individually implemented in each view. 267 * 268 * @tbd improve display method 269 */ 270 public void display() { 271 validate(); 272 setVisible(true); 273 } 274 275 /*** 276 * Selects all the packages in the specified list for all the views 277 * implementing the <code>Observer</code> interface. 278 * 279 * @param selectList List containing all the selected packages. 280 */ 281 public void select(ArrayList selectList){ 282 283 // just selct one package 284 // 285 if ( selectList.size() < 1 ) { 286 clearSelection(); 287 return; 288 } 289 290 // clear all the old selections in the uses tree 291 // 292 if ( m_usesTree != null ) { 293 m_usesTree.getSelectionModel() 294 .removeSelectionPaths(m_usesTree.getSelectionModel().getSelectionPaths()); 295 } 296 297 // clear all the old selections in the is used tree 298 // 299 if ( m_isUsedTree != null ) { 300 m_isUsedTree.getSelectionModel() 301 .removeSelectionPaths(m_isUsedTree.getSelectionModel().getSelectionPaths()); 302 } 303 304 LOG.info("class: " + selectList.get(0)); 305 306 // create root nodes for the two trees 307 // 308 m_usesTreeRoot = new MyTreeNode("'uses' class dependencies"); 309 m_isUsedTreeRoot = new MyTreeNode("'is used' class dependencies"); 310 311 boolean usesFlag = m_uses; // temporary storing flag 312 313 // construct the trees with the classes of this package 314 // 315 m_uses = true; 316 constructRootNodes(m_usesTreeRoot, (String)selectList.get(0)); 317 m_uses = false; // change mode for initialisation 318 constructRootNodes(m_isUsedTreeRoot, (String)selectList.get(0)); 319 320 // reset flag 321 // 322 m_uses = usesFlag; 323 m_usesTree = constructTree(m_usesTreeRoot, "uses"); 324 m_isUsedTree = constructTree(m_isUsedTreeRoot, "is used"); 325 326 // construct uses tree and open first children 327 // 328 int childCount = m_usesTreeRoot.getChildCount(); 329 if ( childCount == 0) { 330 return; 331 } 332 333 // open the tree to the first children 334 // 335 TreeNode[] nodes1 = new TreeNode[2]; 336 nodes1[0] = m_usesTreeRoot; 337 nodes1[1] = m_usesTreeRoot.getChildAt(0); 338 m_usesTree.getSelectionModel().addSelectionPath(new TreePath(nodes1)); 339 m_usesTree.clearSelection(); 340 341 // construct is used tree and open first children 342 // 343 childCount = m_isUsedTreeRoot.getChildCount(); 344 if ( childCount == 0 ) { 345 return; 346 } 347 348 // open the tree to the first children 349 // 350 TreeNode[] nodes2 = new TreeNode[2]; 351 nodes2[0] = m_usesTreeRoot; 352 nodes2[1] = m_usesTreeRoot.getChildAt(0); 353 m_usesTree.getSelectionModel().addSelectionPath(new TreePath(nodes2)); 354 m_usesTree.clearSelection(); 355 356 // show the appropriate tree 357 // 358 if ( m_uses ) { 359 m_treeView.getViewport().remove(m_isUsedTree); 360 m_treeView.getViewport().add(m_usesTree); 361 } 362 else { 363 m_treeView.getViewport().remove(m_usesTree); 364 m_treeView.getViewport().add(m_isUsedTree); 365 } 366 367 // update the tree view 368 // 369 m_treeView.validate(); 370 m_treeView.updateUI(); 371 } 372 373 /*** 374 * Clears all the selections in all the views. 375 */ 376 public void clearSelection(){ 377 m_treeView.getViewport().add(m_emptyLabel); 378 m_treeView.validate(); 379 m_treeView.updateUI(); 380 } 381 382 /*** 383 * Helper method for creating the root nodes for the uses tree. 384 * 385 * @param top Root node of the dependency tree. 386 * @param pack Current selected package. 387 */ 388 private void constructRootNodes(MyTreeNode top, String pack){ 389 390 // get the class dependencies 391 // 392 HashMap classDepend = m_dependencyModel.getRawClassInfos(); 393 394 // get ClassInfos contained by this package 395 ArrayList classList = (ArrayList)classDepend.get(pack); 396 397 // package doesn't contain any classes 398 if ( classList == null ) { 399 clearSelection(); 400 return; 401 } 402 403 // sort the list with the root nodes 404 Collections.sort(classList); 405 406 ListIterator classIter = classList.listIterator(); 407 while ( classIter.hasNext() ) { 408 ClassInfo infoTmp = (ClassInfo)classIter.next(); 409 410 // skip inner and anonymous classes 411 if ( ! (infoTmp.getFullName().lastIndexOf('$') == -1) ) { 412 continue; 413 } 414 415 MyTreeNode newNode 416 = new MyTreeNode(infoTmp.getFullName()); 417 top.add(newNode); 418 419 // distinct the mode 420 if ( m_uses ) { 421 addUsesChildren(newNode); 422 } 423 else { 424 addIsUsedAncestors(newNode); 425 } 426 } 427 } 428 429 430 /*** 431 * Add the next children of the specified package. In the manner of the 432 * 'uses' dependency. 433 * 434 * @param node The node to add the children. 435 */ 436 private void addUsesChildren(MyTreeNode node){ 437 // get class name of this node to determine the children 438 String nodeInfo = (String)node.getUserObject(); 439 440 // get ClassInfo of this class 441 ClassInfo info = (ClassInfo)m_classInfos.get(nodeInfo); 442 // extern classes which have certainly no ClassInfo 443 if ( info == null ) { 444 return; 445 } 446 447 // get all the classes which are used by this class 448 ArrayList usesList = info.getNeededClasses(); 449 Collections.sort(usesList); // sort the list 450 ListIterator children = usesList.listIterator(); 451 452 while ( children.hasNext() ) { 453 String nameTmp = (String)children.next(); 454 455 // skip inner and anonymous classes 456 if ( ! (nameTmp.lastIndexOf('$') == -1) ) { 457 continue; 458 } 459 460 // add children don't add reflexive dependencies 461 if ( ! nodeInfo.equals(nameTmp) ) { 462 MyTreeNode newNode 463 = new MyTreeNode(nameTmp); 464 465 // extract package name 466 int index = 0; 467 if ((index = nameTmp.lastIndexOf(".")) == -1) { 468 index = nameTmp.length(); 469 } 470 String packName = nameTmp.substring(0, index); 471 472 // check if the package is extern 473 if ( ! m_packDepend.containsKey(packName) ) { 474 newNode.iconType = MyTreeNode.EXTERN_ICON_TYPE; 475 } 476 477 try { 478 node.add(newNode); 479 // node cannot be added because of a cycle 480 } catch ( IllegalStateException ise ) {} 481 } 482 } 483 } 484 485 486 /*** 487 * Add the ancestors of the the specified package. In the manner of the 488 * 'is used' dependency. 489 * 490 * @param node The node to add the ancestors. 491 */ 492 private void addIsUsedAncestors(MyTreeNode node){ 493 // determine current package 494 String className = (String)node.getUserObject(); 495 String pack = className.substring(0, className.lastIndexOf(".")); 496 497 // find node of the current package in the graph 498 Node currentPackNode = m_graph.findNodeByName(pack); 499 if ( currentPackNode == null ) { 500 return; 501 } 502 503 // get all the incoming edges of the current node 504 Enumeration inEnum = currentPackNode.inEdgeElements(); 505 506 // list with all the potential 'is used' classes 507 ArrayList isUsedClasses = new ArrayList(); 508 509 // class infos mapped to the package 510 HashMap classInfos = m_dependencyModel.getRawClassInfos(); 511 512 while ( inEnum.hasMoreElements() ) { 513 // get 'is used' packages 514 Node nodeTmp = ((Edge)inEnum.nextElement()).getTail(); 515 String packName = nodeTmp.getName(); 516 // class infos of this package 517 ArrayList isUsedOfPack = (ArrayList)classInfos.get(packName); 518 // tere is no class 519 if ( isUsedOfPack == null ) { 520 continue; 521 } 522 // add to the list of all the potential packages 523 isUsedClasses.addAll(isUsedOfPack); 524 } 525 526 // sort the list 527 Collections.sort(isUsedClasses); 528 529 ListIterator isUsedIter = isUsedClasses.listIterator(); 530 while ( isUsedIter.hasNext() ) { 531 ClassInfo infoTmp = (ClassInfo)isUsedIter.next(); 532 // iterator for checking all the needed classes 533 ListIterator checkIter = infoTmp.getNeededClasses().listIterator(); 534 while ( checkIter.hasNext() ) { 535 String potentialName = (String)checkIter.next(); 536 if ( potentialName.equals(className) ) { 537 String isUsedClass = infoTmp.getFullName(); 538 539 // skip inner and anonymous classes 540 if ( ! (isUsedClass.lastIndexOf('$') == -1) ) { 541 continue; 542 } 543 544 // add children don't add reflexive dependencies 545 if ( ! isUsedClass.equals(className) ) { 546 MyTreeNode newNode 547 = new MyTreeNode(isUsedClass); 548 549 String packName = className.substring(0, 550 className.lastIndexOf(".")); 551 552 // check if the package is extern 553 if ( ! m_packDepend.containsKey(packName) ) { 554 newNode.iconType = MyTreeNode.EXTERN_ICON_TYPE; 555 } 556 557 try { 558 node.add(newNode); 559 // node cannot be added because of a cycle 560 } catch ( IllegalStateException ise ) {} 561 } 562 } 563 } 564 } 565 } 566 567 568 /*** 569 * Changes the mode of the dependency of the package dependency tree. 570 */ 571 private void changeTreeDepend(){ 572 try { 573 if ( m_uses ) { 574 m_treeView.getViewport().remove(m_isUsedTree); 575 m_treeView.getViewport().add(m_usesTree); 576 } 577 else { 578 m_treeView.getViewport().remove(m_usesTree); 579 m_treeView.getViewport().add(m_isUsedTree); 580 } 581 // there is no tree in the viewport at the beginning 582 } catch ( NullPointerException npe) { 583 return; // ignore it and do nothing 584 } 585 m_treeView.validate(); 586 m_treeView.updateUI(); 587 } 588 589 590 /*** 591 * Helper method for selecting a new package. 592 */ 593 private void selectNewPackage(){ 594 // determine the right tree to invoke 595 JTree tree; 596 MyTreeNode root; 597 if ( m_uses ) { 598 tree = m_usesTree; 599 root = m_usesTreeRoot; 600 } 601 else { 602 tree = m_isUsedTree; 603 root = m_isUsedTreeRoot; 604 } 605 606 // no package is selected 607 if ( tree == null ) { 608 return; 609 } 610 611 // get selected componet 612 MyTreeNode nodeTmp 613 = (MyTreeNode)tree.getLastSelectedPathComponent(); 614 615 // nothing is selected or nothing which can be displayed 616 if ( nodeTmp == null || nodeTmp.equals(root) ) { 617 return; 618 } 619 620 // extern packages can't be displayed 621 if ( nodeTmp.iconType.equals(MyTreeNode.EXTERN_ICON_TYPE) ) { 622 JOptionPane.showMessageDialog(this, 623 "Package of this class cannot be selected.\n" + 624 "It is outside of the project.\n", 625 "Extern package", JOptionPane.WARNING_MESSAGE); 626 return; 627 } 628 629 // get the class name 630 String className = (String)nodeTmp.getUserObject(); 631 632 // extract package 633 int lastIndex = className.lastIndexOf("."); 634 String packName = className.substring(0, lastIndex); 635 636 // make the selection consistent 637 ArrayList selectList = new ArrayList(); 638 selectList.add(packName); 639 m_dependencyModel.selectPackages(selectList); 640 } 641 642 643 /*** 644 * Helper class for handling the selection events of the two trees. 645 */ 646 class MyTreeSelectionListener implements TreeSelectionListener { 647 648 /*** 649 * Listener for the tree. 650 * 651 * @param e TreeSelectionEvent thrown by the 652 * <code>TreeSelectionListener</code>. 653 */ 654 public void valueChanged(TreeSelectionEvent e) { 655 MyTreeNode node 656 = (MyTreeNode)m_usesTree 657 .getLastSelectedPathComponent(); 658 // no node is selected 659 if (node == null) { return; } 660 661 Object nodeInfo = node.getUserObject(); 662 LOG.info("Selected node: " + nodeInfo); 663 } 664 } 665 666 /*** 667 * Helper class for handling the expansion events of the two trees. 668 */ 669 class MyTreeExpansionListener implements TreeExpansionListener { 670 671 /*** 672 * Specifies whether it is a 'uses' or a 'is used' dependency tree. 673 */ 674 private String m_mode; 675 676 /*** 677 * Owner. 678 */ 679 private JInternalFrame m_frame; 680 681 /*** 682 * Constructor - Initialize the appropriate tree for application. 683 */ 684 public MyTreeExpansionListener(String mode, JInternalFrame frame){ 685 m_mode = mode; 686 m_frame = frame; 687 } 688 689 // Required by TreeExpansionListener interface. 690 // 691 public void treeExpanded(TreeExpansionEvent e) { 692 693 // add all the children of the expanded node. 694 // 695 MyTreeNode nodeTmp = (MyTreeNode)e.getPath().getLastPathComponent(); 696 697 TreePath path = e.getPath(); 698 int count = path.getPathCount(); 699 Object[] pathComps = path.getPath(); 700 701 702 // add the children of the nodes when expanded 703 // 704 Enumeration childEnum = nodeTmp.children(); 705 while ( childEnum.hasMoreElements() ) { 706 nodeTmp = (MyTreeNode)childEnum.nextElement(); 707 708 String name = (String)nodeTmp.getUserObject(); 709 710 for (int i=count-1 ; i>-1 ; i--) { 711 String tmp 712 = (String)((MyTreeNode)pathComps[i]) 713 .getUserObject(); 714 715 if ( tmp.equals(name) ) { 716 717 // mark the node 718 // 719 TreeNode[] nodes = nodeTmp.getPath(); 720 TreePath treePath = new TreePath(nodes); 721 722 if ( m_uses ) { 723 m_usesTree.getSelectionModel() 724 .addSelectionPath(treePath); 725 } 726 else if ( ! m_uses ) { 727 m_isUsedTree.getSelectionModel() 728 .addSelectionPath(treePath); 729 } 730 731 // change icon of the node with the icon 732 // 733 nodeTmp.iconType = MyTreeNode.CYCLE_ICON_TYPE; 734 nodeTmp.setAllowsChildren(false); 735 } 736 } 737 if ( m_mode.equals("uses") ) { 738 addUsesChildren(nodeTmp); 739 } 740 else { 741 addIsUsedAncestors(nodeTmp); 742 } 743 } 744 } 745 746 // Required by TreeExpansionListener interface. 747 // 748 public void treeCollapsed(TreeExpansionEvent e) { 749 LOG.info("Tree collapsed!"); 750 LOG.info("TreeExpansionPath " + e.getPath()); 751 } 752 } 753 754 /*** 755 * Class for rendering the trees. Particularly for setting the icons. 756 */ 757 private class MyRenderer extends DefaultTreeCellRenderer { 758 759 private ImageIcon m_classIcon = IconGrabber.getIcon("class.gif"); 760 private ImageIcon m_extClassIcon = IconGrabber.getIcon("extClass.gif"); 761 private ImageIcon m_cycleIcon = IconGrabber.getIcon("sun.gif"); 762 763 /*** 764 * Configures the renderer based on the passed in components. 765 * The value is set from messaging the tree with 766 * <code>convertValueToText</code>, which ultimately invokes 767 * <code>toString</code> on <code>value</code>. 768 * The foreground color is set based on the selection and the icon 769 * is set based on on leaf and expanded. 770 */ 771 public Component getTreeCellRendererComponent(JTree tree, 772 Object value, 773 boolean sel, 774 boolean expanded, 775 boolean leaf, 776 int row, 777 boolean hasFocus) { 778 779 super.getTreeCellRendererComponent(tree, value, sel, 780 expanded, leaf, row, 781 hasFocus); 782 783 // current tree node 784 // 785 MyTreeNode treeNode = (MyTreeNode)value; 786 787 // default icon 788 // 789 if ( treeNode.iconType.equals("") ) { 790 setIcon(m_classIcon); 791 } 792 // cycle icon 793 // 794 else if ( treeNode.iconType.equals("cycle") ) { 795 setIcon(m_cycleIcon); 796 } 797 // external package icon 798 // 799 else if ( treeNode.iconType.equals("ext") ) { 800 setIcon(m_extClassIcon); 801 } 802 return this; 803 } 804 } 805 }

This page was automatically generated by Maven