1 19 20 package org.netbeans.modules.java.platform.ui; 21 22 import java.awt.CardLayout ; 23 import java.awt.Component ; 24 import java.awt.Container ; 25 import java.awt.Dialog ; 26 import java.awt.GridBagConstraints ; 27 import java.awt.GridBagLayout ; 28 import java.awt.Image ; 29 import java.beans.PropertyChangeListener ; 30 import java.beans.PropertyChangeEvent ; 31 import java.beans.PropertyVetoException ; 32 import java.beans.VetoableChangeListener ; 33 import java.io.File ; 34 import java.io.IOException ; 35 import java.util.ArrayList ; 36 import java.util.Collections ; 37 import java.util.Comparator ; 38 import java.util.HashMap ; 39 import java.util.Iterator ; 40 import java.util.List ; 41 import java.util.Locale ; 42 import java.util.Set ; 43 import javax.swing.JComponent ; 44 import javax.swing.UIManager ; 45 import org.netbeans.api.java.platform.JavaPlatform; 46 import org.netbeans.api.java.platform.JavaPlatformManager; 47 import org.netbeans.modules.java.platform.wizard.PlatformInstallIterator; 48 import org.openide.DialogDisplayer; 49 import org.openide.ErrorManager; 50 import org.openide.WizardDescriptor; 51 import org.openide.explorer.ExplorerManager; 52 import org.openide.explorer.view.BeanTreeView; 53 import org.openide.filesystems.Repository; 54 import org.openide.filesystems.FileObject; 55 import org.openide.filesystems.FileUtil; 56 import org.openide.loaders.DataObject; 57 import org.openide.loaders.DataFolder; 58 import org.openide.loaders.DataObjectNotFoundException; 59 import org.openide.nodes.AbstractNode; 60 import org.openide.nodes.Node; 61 import org.openide.nodes.FilterNode; 62 import org.openide.nodes.Children; 63 import org.openide.util.NbBundle; 64 65 68 public class PlatformsCustomizer extends javax.swing.JPanel implements PropertyChangeListener , VetoableChangeListener , ExplorerManager.Provider { 69 70 private static final String TEMPLATE = "Templates/Services/Platforms/org-netbeans-api-java-Platform/javaplatform.xml"; private static final String STORAGE = "Services/Platforms/org-netbeans-api-java-Platform"; 73 private PlatformCategoriesChildren children; 74 private ExplorerManager manager; 75 private final JavaPlatform initialPlatform; 76 77 78 public PlatformsCustomizer (JavaPlatform initialPlatform) { 79 this.initialPlatform = (initialPlatform == null) ? 80 JavaPlatformManager.getDefault().getDefaultPlatform() : initialPlatform; 81 initComponents(); 82 } 83 84 85 public void propertyChange(PropertyChangeEvent evt) { 86 if (ExplorerManager.PROP_SELECTED_NODES.equals (evt.getPropertyName())) { 87 Node[] nodes = (Node[]) evt.getNewValue(); 88 if (nodes.length!=1) { 89 selectPlatform (null); 90 } 91 else { 92 selectPlatform (nodes[0]); 93 } 94 } 95 } 96 97 public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { 98 if (ExplorerManager.PROP_SELECTED_NODES.equals (evt.getPropertyName())) { 99 Node[] nodes = (Node[]) evt.getNewValue(); 100 if (nodes.length>1) { 101 throw new PropertyVetoException ("Invalid length",evt); } 103 } 104 } 105 106 107 public synchronized ExplorerManager getExplorerManager() { 108 if (this.manager == null) { 109 this.manager = new ExplorerManager (); 110 this.manager.setRootContext(new AbstractNode (getChildren())); 111 this.manager.addPropertyChangeListener (this); 112 this.manager.addVetoableChangeListener(this); 113 } 114 return manager; 115 } 116 117 public void addNotify () { 118 super.addNotify(); 119 this.expandPlatforms (this.initialPlatform); 120 } 121 122 123 128 private void initComponents() { 130 java.awt.GridBagConstraints gridBagConstraints; 131 132 jPanel3 = new javax.swing.JPanel (); 133 platforms = new PlatformsView (); 134 addButton = new javax.swing.JButton (); 135 removeButton = new javax.swing.JButton (); 136 cards = new javax.swing.JPanel (); 137 jPanel1 = new javax.swing.JPanel (); 138 jLabel1 = new javax.swing.JLabel (); 139 platformName = new javax.swing.JTextField (); 140 jLabel2 = new javax.swing.JLabel (); 141 platformHome = new javax.swing.JTextField (); 142 clientArea = new javax.swing.JPanel (); 143 messageArea = new javax.swing.JPanel (); 144 jLabel3 = new javax.swing.JLabel (); 145 146 setLayout(new java.awt.GridBagLayout ()); 147 148 platforms.setBorder(null); 149 platforms.setPreferredSize(new java.awt.Dimension (200, 334)); 150 gridBagConstraints = new java.awt.GridBagConstraints (); 151 gridBagConstraints.gridx = 0; 152 gridBagConstraints.gridy = 1; 153 gridBagConstraints.gridwidth = 2; 154 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; 155 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 156 gridBagConstraints.weighty = 1.0; 157 gridBagConstraints.insets = new java.awt.Insets (2, 12, 12, 6); 158 add(platforms, gridBagConstraints); 159 java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("org/netbeans/modules/java/platform/ui/Bundle"); platforms.getAccessibleContext().setAccessibleName(bundle.getString("AN_PlatformsCustomizerPlatforms")); platforms.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_PlatformsCustomizerPlatforms")); 163 addButton.setMnemonic(java.util.ResourceBundle.getBundle("org/netbeans/modules/java/platform/ui/Bundle").getString("MNE_AddPlatform").charAt(0)); 164 addButton.setText(bundle.getString("CTL_AddPlatform")); addButton.addActionListener(new java.awt.event.ActionListener () { 166 public void actionPerformed(java.awt.event.ActionEvent evt) { 167 addNewPlatform(evt); 168 } 169 }); 170 gridBagConstraints = new java.awt.GridBagConstraints (); 171 gridBagConstraints.gridx = 0; 172 gridBagConstraints.gridy = 2; 173 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 174 gridBagConstraints.insets = new java.awt.Insets (0, 12, 0, 6); 175 add(addButton, gridBagConstraints); 176 addButton.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_AddPlatform")); 178 removeButton.setMnemonic(java.util.ResourceBundle.getBundle("org/netbeans/modules/java/platform/ui/Bundle").getString("MNE_Remove").charAt(0)); 179 removeButton.setText(bundle.getString("CTL_Remove")); removeButton.addActionListener(new java.awt.event.ActionListener () { 181 public void actionPerformed(java.awt.event.ActionEvent evt) { 182 removePlatform(evt); 183 } 184 }); 185 gridBagConstraints = new java.awt.GridBagConstraints (); 186 gridBagConstraints.gridx = 1; 187 gridBagConstraints.gridy = 2; 188 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 189 gridBagConstraints.insets = new java.awt.Insets (0, 6, 0, 6); 190 add(removeButton, gridBagConstraints); 191 removeButton.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_Remove")); 193 cards.setLayout(new java.awt.CardLayout ()); 194 195 jPanel1.setLayout(new java.awt.GridBagLayout ()); 196 197 jLabel1.setDisplayedMnemonic(java.util.ResourceBundle.getBundle("org/netbeans/modules/java/platform/ui/Bundle").getString("MNE_PlatformName").charAt(0)); 198 jLabel1.setLabelFor(platformName); 199 jLabel1.setText(bundle.getString("CTL_PlatformName")); gridBagConstraints = new java.awt.GridBagConstraints (); 201 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 202 jPanel1.add(jLabel1, gridBagConstraints); 203 204 platformName.setColumns(25); 205 platformName.setEditable(false); 206 gridBagConstraints = new java.awt.GridBagConstraints (); 207 gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; 208 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 209 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 210 gridBagConstraints.weightx = 1.0; 211 gridBagConstraints.insets = new java.awt.Insets (0, 6, 0, 0); 212 jPanel1.add(platformName, gridBagConstraints); 213 platformName.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_PlatformName")); 215 jLabel2.setDisplayedMnemonic(java.util.ResourceBundle.getBundle("org/netbeans/modules/java/platform/ui/Bundle").getString("MNE_PlatformHome").charAt(0)); 216 jLabel2.setLabelFor(platformHome); 217 jLabel2.setText(bundle.getString("CTL_PlatformHome")); gridBagConstraints = new java.awt.GridBagConstraints (); 219 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 220 gridBagConstraints.insets = new java.awt.Insets (6, 0, 12, 0); 221 jPanel1.add(jLabel2, gridBagConstraints); 222 223 platformHome.setColumns(25); 224 platformHome.setEditable(false); 225 gridBagConstraints = new java.awt.GridBagConstraints (); 226 gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; 227 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 228 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 229 gridBagConstraints.weightx = 1.0; 230 gridBagConstraints.insets = new java.awt.Insets (6, 6, 12, 0); 231 jPanel1.add(platformHome, gridBagConstraints); 232 platformHome.getAccessibleContext().setAccessibleDescription(bundle.getString("AD_PlatformHome")); 234 clientArea.setLayout(new java.awt.GridBagLayout ()); 235 gridBagConstraints = new java.awt.GridBagConstraints (); 236 gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; 237 gridBagConstraints.gridheight = java.awt.GridBagConstraints.REMAINDER; 238 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; 239 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 240 gridBagConstraints.weightx = 1.0; 241 gridBagConstraints.weighty = 1.0; 242 jPanel1.add(clientArea, gridBagConstraints); 243 244 cards.add(jPanel1, "card2"); 245 246 messageArea.setLayout(new java.awt.GridBagLayout ()); 247 cards.add(messageArea, "card3"); 248 249 gridBagConstraints = new java.awt.GridBagConstraints (); 250 gridBagConstraints.gridx = 2; 251 gridBagConstraints.gridy = 1; 252 gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; 253 gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; 254 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 255 gridBagConstraints.weightx = 1.0; 256 gridBagConstraints.weighty = 1.0; 257 gridBagConstraints.insets = new java.awt.Insets (2, 6, 12, 12); 258 add(cards, gridBagConstraints); 259 260 jLabel3.setLabelFor(platforms); 261 org.openide.awt.Mnemonics.setLocalizedText(jLabel3, bundle.getString("TXT_PlatformsList")); gridBagConstraints = new java.awt.GridBagConstraints (); 263 gridBagConstraints.gridx = 0; 264 gridBagConstraints.gridy = 0; 265 gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; 266 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 267 gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST; 268 gridBagConstraints.insets = new java.awt.Insets (12, 12, 0, 12); 269 add(jLabel3, gridBagConstraints); 270 271 getAccessibleContext().setAccessibleDescription(bundle.getString("AD_PlatformsCustomizer")); } 274 private void removePlatform(java.awt.event.ActionEvent evt) { Node[] nodes = getExplorerManager().getSelectedNodes(); 276 if (nodes.length!=1) { 277 assert false : "Illegal number of selected nodes"; return; 279 } 280 DataObject dobj = (DataObject) nodes[0].getLookup().lookup (DataObject.class); 281 if (dobj == null) { 282 assert false : "Can not find platform definition for node: "+ nodes[0].getDisplayName(); return; 284 } 285 try { 286 dobj.delete(); 287 this.getChildren().refreshPlatforms(); 288 this.expandPlatforms(null); 289 } catch (IOException ioe) { 290 ErrorManager.getDefault().notify (ioe); 291 } 292 } 294 private void addNewPlatform(java.awt.event.ActionEvent evt) { try { 296 WizardDescriptor wiz = new WizardDescriptor (PlatformInstallIterator.create()); 297 DataObject template = DataObject.find ( 298 Repository.getDefault().getDefaultFileSystem().findResource(TEMPLATE)); 299 wiz.putProperty("targetTemplate", template); DataFolder folder = DataFolder.findFolder( 301 Repository.getDefault().getDefaultFileSystem().findResource(STORAGE)); 302 wiz.putProperty("targetFolder",folder); wiz.putProperty("WizardPanel_autoWizardStyle", Boolean.TRUE); wiz.putProperty("WizardPanel_contentDisplayed", Boolean.TRUE); wiz.putProperty("WizardPanel_contentNumbered", Boolean.TRUE); wiz.setTitle(NbBundle.getMessage(PlatformsCustomizer.class,"CTL_AddPlatformTitle")); 307 wiz.setTitleFormat(new java.text.MessageFormat ("{0}")); Dialog dlg = DialogDisplayer.getDefault().createDialog(wiz); 309 try { 310 dlg.setVisible(true); 311 if (wiz.getValue() == WizardDescriptor.FINISH_OPTION) { 312 this.getChildren().refreshPlatforms(); 313 Set result = wiz.getInstantiatedObjects(); 314 this.expandPlatforms (result.size() == 0 ? null : (JavaPlatform)result.iterator().next()); 315 } 316 } finally { 317 dlg.dispose(); 318 } 319 } catch (DataObjectNotFoundException dfne) { 320 ErrorManager.getDefault().notify (dfne); 321 } 322 catch (IOException ioe) { 323 ErrorManager.getDefault().notify (ioe); 324 } 325 } 327 328 private synchronized PlatformCategoriesChildren getChildren () { 329 if (this.children == null) { 330 this.children = new PlatformCategoriesChildren (); 331 } 332 return this.children; 333 } 334 335 private void selectPlatform (Node pNode) { 336 this.clientArea.removeAll(); 337 this.messageArea.removeAll(); 338 this.removeButton.setEnabled (false); 339 if (pNode == null) { 340 ((CardLayout )cards.getLayout()).last(cards); 341 return; 342 } 343 JComponent target = messageArea; 344 JavaPlatform platform = (JavaPlatform) pNode.getLookup().lookup(JavaPlatform.class); 345 if (platform != null) { 346 this.removeButton.setEnabled (isDefaultPLatform(platform)); 347 if (platform.getInstallFolders().size() != 0) { 348 this.platformName.setText(pNode.getDisplayName()); 349 Iterator it = platform.getInstallFolders().iterator(); 350 if (it.hasNext()) { 351 File file = FileUtil.toFile ((FileObject)it.next()); 352 if (file != null) { 353 this.platformHome.setText (file.getAbsolutePath()); 354 } 355 } 356 target = clientArea; 357 } 358 } 359 if (pNode.hasCustomizer()) { 360 Component component = pNode.getCustomizer(); 361 if (component != null) { 362 addComponent(target, component); 363 } 364 } 365 target.revalidate(); 366 CardLayout cl = (CardLayout ) cards.getLayout(); 367 if (target == clientArea) { 368 cl.first (cards); 369 } 370 else { 371 cl.last (cards); 372 } 373 } 374 375 private static void addComponent (Container container, Component component) { 376 GridBagConstraints c = new GridBagConstraints (); 377 c.gridx = c.gridy = GridBagConstraints.RELATIVE; 378 c.gridheight = c.gridwidth = GridBagConstraints.REMAINDER; 379 c.fill = GridBagConstraints.BOTH; 380 c.anchor = GridBagConstraints.NORTHWEST; 381 c.weightx = c.weighty = 1.0; 382 ((GridBagLayout )container.getLayout()).setConstraints (component,c); 383 container.add (component); 384 } 385 386 private static boolean isDefaultPLatform (JavaPlatform platform) { 387 JavaPlatform defaultPlatform = JavaPlatformManager.getDefault().getDefaultPlatform(); 388 return defaultPlatform!=null && !defaultPlatform.equals(platform); 389 } 390 391 private void expandPlatforms (JavaPlatform platform) { 392 ExplorerManager mgr = this.getExplorerManager(); 393 Node node = mgr.getRootContext(); 394 expandAllNodes(this.platforms, node, mgr, platform); 395 } 396 397 private static void expandAllNodes (BeanTreeView btv, Node node, ExplorerManager mgr, JavaPlatform platform) { 398 btv.expandNode (node); 399 Children ch = node.getChildren(); 400 if ( ch == Children.LEAF ) { 401 if (platform != null && platform.equals(node.getLookup().lookup(JavaPlatform.class))) { 402 try { 403 mgr.setSelectedNodes (new Node[] {node}); 404 } catch (PropertyVetoException e) { 405 } 407 } 408 return; 409 } 410 Node nodes[] = ch.getNodes( true ); 411 for ( int i = 0; i < nodes.length; i++ ) { 412 expandAllNodes( btv, nodes[i], mgr, platform); 413 } 414 415 } 416 417 418 private javax.swing.JButton addButton; 420 private javax.swing.JPanel cards; 421 private javax.swing.JPanel clientArea; 422 private javax.swing.JLabel jLabel1; 423 private javax.swing.JLabel jLabel2; 424 private javax.swing.JLabel jLabel3; 425 private javax.swing.JPanel jPanel1; 426 private javax.swing.JPanel jPanel3; 427 private javax.swing.JPanel messageArea; 428 private javax.swing.JTextField platformHome; 429 private javax.swing.JTextField platformName; 430 private org.openide.explorer.view.BeanTreeView platforms; 431 private javax.swing.JButton removeButton; 432 434 435 private static class PlatformsView extends BeanTreeView { 436 437 public PlatformsView () { 438 super (); 439 this.setPopupAllowed (false); 440 this.setDefaultActionAllowed(false); 441 this.setRootVisible (false); 442 this.tree.setEditable(false); 443 this.tree.setShowsRootHandles(false); 444 this.setBorder(UIManager.getBorder("Nb.ScrollPane.border")); } 446 447 } 448 449 private static class PlatformCategoriesDescriptor implements Comparable { 450 private final String categoryName; 451 private final List platforms; 452 private boolean changed = false; 453 454 public PlatformCategoriesDescriptor (String categoryName) { 455 assert categoryName != null; 456 this.categoryName = categoryName; 457 this.platforms = new ArrayList (); 458 } 459 460 public String getName () { 461 return this.categoryName; 462 } 463 464 public List getPlatform () { 465 if (changed) { 466 Collections.sort(this.platforms, new PlatformNodeComparator()); 469 changed = false; 470 } 471 return Collections.unmodifiableList (this.platforms); 472 } 473 474 public void add (Node node) { 475 this.platforms.add (node); 476 this.changed = true; 477 } 478 479 public int hashCode () { 480 return this.categoryName.hashCode (); 481 } 482 483 public boolean equals (Object other) { 484 if (other instanceof PlatformCategoriesDescriptor) { 485 PlatformCategoriesDescriptor desc = (PlatformCategoriesDescriptor) other; 486 return this.categoryName.equals(desc.categoryName) && 487 this.platforms.size() == desc.platforms.size(); 488 } 489 return false; 490 } 491 492 public int compareTo(Object other) { 493 if (!(other instanceof PlatformCategoriesDescriptor )) { 494 throw new IllegalArgumentException (); 495 } 496 PlatformCategoriesDescriptor desc = (PlatformCategoriesDescriptor) other; 497 return this.categoryName.compareTo (desc.categoryName); 498 } 499 500 } 501 502 private static class PlatformsChildren extends Children.Keys { 503 504 private List platforms; 505 506 public PlatformsChildren (List platforms) { 507 this.platforms = platforms; 508 } 509 510 protected void addNotify() { 511 super.addNotify(); 512 this.setKeys (this.platforms); 513 } 514 515 protected void removeNotify() { 516 super.removeNotify(); 517 this.setKeys(new Object [0]); 518 } 519 520 protected Node[] createNodes(Object key) { 521 return new Node[] {new FilterNode((Node) key, Children.LEAF)}; 522 } 523 } 524 525 private static class PlatformCategoryNode extends AbstractNode { 526 527 private final PlatformCategoriesDescriptor desc; 528 private Node iconDelegate; 529 530 public PlatformCategoryNode (PlatformCategoriesDescriptor desc) { 531 super (new PlatformsChildren (desc.getPlatform())); 532 this.desc = desc; 533 this.iconDelegate = DataFolder.findFolder(Repository.getDefault().getDefaultFileSystem().getRoot()).getNodeDelegate(); 534 } 535 536 public String getName () { 537 return this.desc.getName (); 538 } 539 540 public String getDisplayName () { 541 return this.getName (); 542 } 543 544 public Image getIcon(int type) { 545 return this.iconDelegate.getIcon(type); 546 } 547 548 public Image getOpenedIcon(int type) { 549 return this.iconDelegate.getOpenedIcon (type); 550 } 551 552 } 553 554 private static class PlatformCategoriesChildren extends Children.Keys { 555 556 protected void addNotify () { 557 super.addNotify (); 558 this.refreshPlatforms (); 559 } 560 561 protected void removeNotify () { 562 super.removeNotify (); 563 } 564 565 protected Node[] createNodes(Object key) { 566 if (key instanceof PlatformCategoriesDescriptor) { 567 PlatformCategoriesDescriptor desc = (PlatformCategoriesDescriptor) key; 568 return new Node[] { 569 new PlatformCategoryNode (desc) 570 }; 571 } 572 else if (key instanceof Node) { 573 return new Node[] { 574 new FilterNode ((Node)key,Children.LEAF) 575 }; 576 } 577 else { 578 return new Node[0]; 579 } 580 } 581 582 private void refreshPlatforms () { 583 FileObject storage = Repository.getDefault().getDefaultFileSystem().findResource(STORAGE); 584 if (storage != null) { 585 HashMap categories = new HashMap (); 586 FileObject[] children = storage.getChildren(); 587 for (int i=0; i< children.length; i++) { 588 try { 589 DataObject dobj = DataObject.find (children[i]); 590 Node node = dobj.getNodeDelegate(); 591 JavaPlatform platform = (JavaPlatform) node.getLookup().lookup(JavaPlatform.class); 592 if (platform != null) { 593 String platformType = platform.getSpecification().getName(); 594 if (platformType != null) { 595 platformType = platformType.toUpperCase(Locale.ENGLISH); 596 PlatformCategoriesDescriptor platforms = (PlatformCategoriesDescriptor) categories.get (platformType); 597 if (platforms == null ) { 598 platforms = new PlatformCategoriesDescriptor (platformType); 599 categories.put (platformType, platforms); 600 } 601 platforms.add (node); 602 } 603 else { 604 ErrorManager.getDefault().log ("Platform: "+ platform.getDisplayName() +" has invalid specification."); } 606 } 607 else { 608 ErrorManager.getDefault().log ("Platform node for : "+node.getDisplayName()+" has no platform in its lookup."); } 610 }catch (DataObjectNotFoundException e) { 611 ErrorManager.getDefault().notify(e); 612 } 613 } 614 List keys = new ArrayList (categories.values()); 615 Collections.sort (keys); 621 this.setKeys(keys); 622 } 624 } 625 626 627 } 628 629 private static class PlatformNodeComparator implements Comparator { 630 631 public int compare (Object o1, Object o2) { 632 if (!(o1 instanceof Node) || !(o2 instanceof Node)) { 633 throw new IllegalArgumentException (); 634 } 635 String dn1 = ((Node)o1).getDisplayName(); 636 String dn2 = ((Node)o2).getDisplayName(); 637 return dn1.compareTo(dn2); 638 } 639 } 640 641 } 642 | Popular Tags |