Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)
Frames | No Frames

Source for javax.swing.JTree

 1:  /* JTree.java 
 2:  Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
 3:  
 4: This file is part of GNU Classpath.
 5: 
 6: GNU Classpath is free software; you can redistribute it and/or modify
 7: it under the terms of the GNU General Public License as published by
 8: the Free Software Foundation; either version 2, or (at your option)
 9: any later version.
 10: 
 11: GNU Classpath is distributed in the hope that it will be useful, but
 12: WITHOUT ANY WARRANTY; without even the implied warranty of
 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 14: General Public License for more details.
 15: 
 16: You should have received a copy of the GNU General Public License
 17: along with GNU Classpath; see the file COPYING. If not, write to the
 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 19: 02110-1301 USA.
 20: 
 21: Linking this library statically or dynamically with other modules is
 22: making a combined work based on this library. Thus, the terms and
 23: conditions of the GNU General Public License cover the whole
 24: combination.
 25: 
 26: As a special exception, the copyright holders of this library give you
 27: permission to link this library with independent modules to produce an
 28: executable, regardless of the license terms of these independent
 29: modules, and to copy and distribute the resulting executable under
 30: terms of your choice, provided that you also meet, for each linked
 31: independent module, the terms and conditions of the license of that
 32: module. An independent module is a module which is not derived from
 33: or based on this library. If you modify this library, you may extend
 34: this exception to your version of the library, but you are not
 35: obligated to do so. If you do not wish to do so, delete this
 36: exception statement from your version. */
 37: 
 38:  package javax.swing;
 39: 
 40:  import java.awt.Color;
 41:  import java.awt.Cursor;
 42:  import java.awt.Dimension;
 43:  import java.awt.Font;
 44:  import java.awt.FontMetrics;
 45:  import java.awt.Point;
 46:  import java.awt.Rectangle;
 47:  import java.awt.event.FocusListener;
 48:  import java.beans.PropertyChangeListener;
 49:  import java.io.Serializable;
 50:  import java.util.Enumeration;
 51:  import java.util.Hashtable;
 52:  import java.util.Iterator;
 53:  import java.util.Locale;
 54:  import java.util.Vector;
 55: 
 56:  import javax.accessibility.Accessible;
 57:  import javax.accessibility.AccessibleAction;
 58:  import javax.accessibility.AccessibleComponent;
 59:  import javax.accessibility.AccessibleContext;
 60:  import javax.accessibility.AccessibleRole;
 61:  import javax.accessibility.AccessibleSelection;
 62:  import javax.accessibility.AccessibleState;
 63:  import javax.accessibility.AccessibleStateSet;
 64:  import javax.accessibility.AccessibleText;
 65:  import javax.accessibility.AccessibleValue;
 66:  import javax.swing.event.TreeExpansionEvent;
 67:  import javax.swing.event.TreeExpansionListener;
 68:  import javax.swing.event.TreeModelEvent;
 69:  import javax.swing.event.TreeModelListener;
 70:  import javax.swing.event.TreeSelectionEvent;
 71:  import javax.swing.event.TreeSelectionListener;
 72:  import javax.swing.event.TreeWillExpandListener;
 73:  import javax.swing.plaf.TreeUI;
 74:  import javax.swing.text.Position;
 75:  import javax.swing.tree.DefaultMutableTreeNode;
 76:  import javax.swing.tree.DefaultTreeModel;
 77:  import javax.swing.tree.DefaultTreeSelectionModel;
 78:  import javax.swing.tree.ExpandVetoException;
 79:  import javax.swing.tree.TreeCellEditor;
 80:  import javax.swing.tree.TreeCellRenderer;
 81:  import javax.swing.tree.TreeModel;
 82:  import javax.swing.tree.TreeNode;
 83:  import javax.swing.tree.TreePath;
 84:  import javax.swing.tree.TreeSelectionModel;
 85: 
 86:  public class JTree extends JComponent implements Scrollable, Accessible
 87: {
 88: 
 89:  /**
 90:  * This class implements accessibility support for the JTree class. It 
 91:  * provides an implementation of the Java Accessibility API appropriate 
 92:  * to tree user-interface elements.
 93:  */
 94:  protected class AccessibleJTree extends JComponent.AccessibleJComponent
 95:  implements AccessibleSelection, TreeSelectionListener, TreeModelListener,
 96:  TreeExpansionListener
 97:  {
 98:  
 99:  /**
 100:  * This class implements accessibility support for the JTree child. It provides 
 101:  * an implementation of the Java Accessibility API appropriate to tree nodes.
 102:  */
 103:  protected class AccessibleJTreeNode extends AccessibleContext 
 104:  implements Accessible, AccessibleComponent, AccessibleSelection, 
 105:  AccessibleAction
 106:  {
 107:  
 108:  private JTree tree;
 109:  private TreePath tp;
 110:  private Accessible acc;
 111:  private AccessibleStateSet states;
 112:  private Vector selectionList;
 113:  private Vector actionList;
 114:  private TreeModel mod;
 115:  private Cursor cursor;
 116:  
 117:  /**
 118:  * Constructs an AccessibleJTreeNode
 119:  * 
 120:  * @param t - the current tree
 121:  * @param p - the current path to be dealt with
 122:  * @param ap - the accessible object to use
 123:  */
 124:  public AccessibleJTreeNode(JTree t, TreePath p, Accessible ap)
 125:  {
 126:  states = new AccessibleStateSet();
 127:  selectionList = new Vector();
 128:  actionList = new Vector();
 129:  mod = tree.getModel();
 130:  cursor = JTree.this.getCursor();
 131:  
 132:  tree = t;
 133:  tp = p;
 134:  acc = ap;
 135:  
 136:  // Add all the children of this path that may already be
 137:  // selected to the selection list.
 138:  TreePath[] selected = tree.getSelectionPaths();
 139:  for (int i = 0; i < selected.length; i++)
 140:  {
 141:  TreePath sel = selected[i];
 142:  if ((sel.getParentPath()).equals(tp))
 143:  selectionList.add(sel);
 144:  }
 145:  
 146:  // Add all the actions available for a node to 
 147:  // the action list.
 148:  actionList.add("EXPAND");
 149:  actionList.add("COLLAPSE");
 150:  actionList.add("EDIT");
 151:  actionList.add("SELECT");
 152:  actionList.add("DESELECT");
 153:  } 
 154:  
 155:  /**
 156:  * Adds the specified selected item in the object to the object's
 157:  * selection.
 158:  * 
 159:  * @param i - the i-th child of this node.
 160:  */
 161:  public void addAccessibleSelection(int i)
 162:  {
 163:  if (mod != null)
 164:  {
 165:  Object child = mod.getChild(tp.getLastPathComponent(), i);
 166:  if (child != null)
 167:  {
 168:  if (!states.contains(AccessibleState.MULTISELECTABLE))
 169:  clearAccessibleSelection();
 170:  selectionList.add(child); 
 171:  tree.addSelectionPath(tp.pathByAddingChild(child));
 172:  }
 173:  }
 174:  }
 175:  
 176:  /**
 177:  * Adds the specified focus listener to receive focus events 
 178:  * from this component.
 179:  * 
 180:  * @param l - the new focus listener
 181:  */
 182:  public void addFocusListener(FocusListener l)
 183:  {
 184:  tree.addFocusListener(l);
 185:  }
 186:  
 187:  /**
 188:  * Add a PropertyChangeListener to the listener list.
 189:  * 
 190:  * @param l - the new property change listener
 191:  */
 192:  public void addPropertyChangeListener(PropertyChangeListener l)
 193:  {
 194:  // Nothing to do here.
 195:  }
 196:  
 197:  /**
 198:  * Clears the selection in the object, so that nothing in the 
 199:  * object is selected.
 200:  */
 201:  public void clearAccessibleSelection()
 202:  {
 203:  selectionList.clear();
 204:  }
 205:  
 206:  /**
 207:  * Checks whether the specified point is within this object's 
 208:  * bounds, where the point's x and y coordinates are defined to be 
 209:  * relative to the coordinate system of the object. 
 210:  * 
 211:  * @param p - the point to check
 212:  * @return true if p is in the bounds
 213:  */
 214:  public boolean contains(Point p)
 215:  {
 216:  return getBounds().contains(p);
 217:  }
 218:  
 219:  /**
 220:  * Perform the specified Action on the tree node.
 221:  * 
 222:  * @param i - the i-th action to perform
 223:  * @return true if the the action was performed; else false.
 224:  */
 225:  public boolean doAccessibleAction(int i)
 226:  {
 227:  if (i >= actionList.size() || i < 0)
 228:  return false;
 229:  
 230:  if (actionList.get(i).equals("EXPAND"))
 231:  tree.expandPath(tp);
 232:  else if (actionList.get(i).equals("COLLAPSE"))
 233:  tree.collapsePath(tp);
 234:  else if (actionList.get(i).equals("SELECT"))
 235:  tree.addSelectionPath(tp);
 236:  else if (actionList.get(i).equals("DESELECT"))
 237:  tree.removeSelectionPath(tp);
 238:  else if (actionList.get(i).equals("EDIT"))
 239:  tree.startEditingAtPath(tp);
 240:  else
 241:  return false;
 242:  return true;
 243:  }
 244:  
 245:  /**
 246:  * Get the AccessibleAction associated with this object.
 247:  * 
 248:  * @return the action
 249:  */
 250:  public AccessibleAction getAccessibleAction()
 251:  {
 252:  return this;
 253:  }
 254:  
 255:  /**
 256:  * Returns the number of accessible actions available in this tree node.
 257:  * 
 258:  * @return the number of actions
 259:  */
 260:  public int getAccessibleActionCount()
 261:  {
 262:  return actionList.size();
 263:  }
 264:  
 265:  /**
 266:  * Return a description of the specified action of the tree node.
 267:  * 
 268:  * @param i - the i-th action's description
 269:  * @return a description of the action
 270:  */
 271:  public String getAccessibleActionDescription(int i)
 272:  {
 273:  if (i < 0 || i >= actionList.size())
 274:  return (actionList.get(i)).toString();
 275:  return super.getAccessibleDescription();
 276:  }
 277:  
 278:  /**
 279:  * Returns the Accessible child, if one exists, contained at the 
 280:  * local coordinate Point.
 281:  * 
 282:  * @param p - the point of the accessible
 283:  * @return the accessible at point p if it exists
 284:  */
 285:  public Accessible getAccessibleAt(Point p)
 286:  {
 287:  TreePath acc = tree.getClosestPathForLocation(p.x, p.y);
 288:  if (acc != null)
 289:  return new AccessibleJTreeNode(tree, acc, this);
 290:  return null;
 291:  }
 292:  
 293:  /**
 294:  * Return the specified Accessible child of the object.
 295:  * 
 296:  * @param i - the i-th child of the current path
 297:  * @return the child if it exists
 298:  */
 299:  public Accessible getAccessibleChild(int i)
 300:  {
 301:  if (mod != null)
 302:  {
 303:  Object child = mod.getChild(tp.getLastPathComponent(), i);
 304:  if (child != null)
 305:  return new AccessibleJTreeNode(tree, tp.pathByAddingChild(child),
 306:  acc);
 307:  }
 308:  return null;
 309:  }
 310:  
 311:  /**
 312:  * Returns the number of accessible children in the object.
 313:  * 
 314:  * @return the number of children the current node has
 315:  */
 316:  public int getAccessibleChildrenCount()
 317:  {
 318:  TreeModel mod = getModel();
 319:  if (mod != null)
 320:  return mod.getChildCount(tp.getLastPathComponent());
 321:  return 0;
 322:  }
 323:  
 324:  /**
 325:  * Get the AccessibleComponent associated with this object.
 326:  * 
 327:  * @return the accessible component if it is supported.
 328:  */
 329:  public AccessibleComponent getAccessibleComponent()
 330:  {
 331:  return this;
 332:  }
 333:  
 334:  /**
 335:  * Get the AccessibleContext associated with this tree node.
 336:  * 
 337:  * @return an instance of this class
 338:  */
 339:  public AccessibleContext getAccessibleContext()
 340:  {
 341:  return this;
 342:  }
 343:  
 344:  /**
 345:  * Get the accessible description of this object.
 346:  * 
 347:  * @return the accessible description
 348:  */
 349:  public String getAccessibleDescription()
 350:  {
 351:  return super.getAccessibleDescription();
 352:  }
 353:  
 354:  /**
 355:  * Get the index of this object in its accessible parent.
 356:  * 
 357:  * @return the index of this in the parent.
 358:  */
 359:  public int getAccessibleIndexInParent()
 360:  {
 361:  AccessibleContext parent = getAccessibleParent().getAccessibleContext();
 362:  if (parent != null)
 363:  for (int i = 0; i < parent.getAccessibleChildrenCount(); i++)
 364:  {
 365:  if ((parent.getAccessibleChild(i)).equals(this))
 366:  return i;
 367:  }
 368:  return -1;
 369:  }
 370:  
 371:  /**
 372:  * Get the accessible name of this object.
 373:  * 
 374:  * @return the accessible name
 375:  */
 376:  public String getAccessibleName()
 377:  {
 378:  return super.getAccessibleName();
 379:  }
 380:  
 381:  /**
 382:  * Get the Accessible parent of this object.
 383:  * 
 384:  * @return the accessible parent if it exists.
 385:  */
 386:  public Accessible getAccessibleParent()
 387:  {
 388:  return super.getAccessibleParent();
 389:  }
 390:  
 391:  /**
 392:  * Get the role of this object.
 393:  * 
 394:  * @return the accessible role
 395:  */
 396:  public AccessibleRole getAccessibleRole()
 397:  {
 398:  return AccessibleJTree.this.getAccessibleRole();
 399:  }
 400:  
 401:  /**
 402:  * Get the AccessibleSelection associated with this object if one exists.
 403:  * 
 404:  * @return the accessible selection for this.
 405:  */
 406:  public AccessibleSelection getAccessibleSelection()
 407:  {
 408:  return this;
 409:  }
 410:  
 411:  /**
 412:  * Returns an Accessible representing the specified selected item 
 413:  * in the object.
 414:  * 
 415:  * @return the accessible representing a certain selected item.
 416:  */
 417:  public Accessible getAccessibleSelection(int i)
 418:  {
 419:  if (i > 0 && i < getAccessibleSelectionCount())
 420:  return new AccessibleJTreeNode(tree, 
 421:  tp.pathByAddingChild(selectionList.get(i)), acc);
 422:  return null;
 423:  }
 424:  
 425:  /**
 426:  * Returns the number of items currently selected.
 427:  * 
 428:  * @return the number of items selected.
 429:  */
 430:  public int getAccessibleSelectionCount()
 431:  {
 432:  return selectionList.size();
 433:  }
 434:  
 435:  /**
 436:  * Get the state set of this object.
 437:  * 
 438:  * @return the state set for this object
 439:  */
 440:  public AccessibleStateSet getAccessibleStateSet()
 441:  {
 442:  if (isVisible())
 443:  states.add(AccessibleState.VISIBLE);
 444:  if (tree.isCollapsed(tp))
 445:  states.add(AccessibleState.COLLAPSED);
 446:  if (tree.isEditable())
 447:  states.add(AccessibleState.EDITABLE);
 448:  if (mod != null && 
 449:  !mod.isLeaf(tp.getLastPathComponent()))
 450:  states.add(AccessibleState.EXPANDABLE);
 451:  if (tree.isExpanded(tp))
 452:  states.add(AccessibleState.EXPANDED);
 453:  if (isFocusable())
 454:  states.add(AccessibleState.FOCUSABLE);
 455:  if (hasFocus())
 456:  states.add(AccessibleState.FOCUSED);
 457:  if (tree.getSelectionModel().getSelectionMode() != 
 458:  TreeSelectionModel.SINGLE_TREE_SELECTION)
 459:  states.add(AccessibleState.MULTISELECTABLE);
 460:  if (tree.isOpaque())
 461:  states.add(AccessibleState.OPAQUE);
 462:  if (tree.isPathSelected(tp))
 463:  states.add(AccessibleState.SELECTED);
 464:  if (isShowing())
 465:  states.add(AccessibleState.SHOWING);
 466: 
 467:  states.add(AccessibleState.SELECTABLE);
 468:  return states;
 469:  }
 470:  
 471:  /**
 472:  * Get the AccessibleText associated with this object if one exists.
 473:  * 
 474:  * @return the accessible text
 475:  */
 476:  public AccessibleText getAccessibleText()
 477:  {
 478:  return super.getAccessibleText();
 479:  }
 480:  
 481:  /**
 482:  * Get the AccessibleValue associated with this object if one exists.
 483:  * 
 484:  * @return the accessible value if it exists
 485:  */
 486:  public AccessibleValue getAccessibleValue()
 487:  {
 488:  return super.getAccessibleValue();
 489:  }
 490:  
 491:  /**
 492:  * Get the background color of this object.
 493:  * 
 494:  * @return the color of the background.
 495:  */
 496:  public Color getBackground()
 497:  {
 498:  return tree.getBackground();
 499:  }
 500:  
 501:  /**
 502:  * Gets the bounds of this object in the form of a Rectangle object.
 503:  * 
 504:  * @return the bounds of the current node.
 505:  */
 506:  public Rectangle getBounds()
 507:  {
 508:  return tree.getPathBounds(tp);
 509:  }
 510:  
 511:  /**
 512:  * Gets the Cursor of this object.
 513:  * 
 514:  * @return the cursor for the current node
 515:  */
 516:  public Cursor getCursor()
 517:  {
 518:  return cursor;
 519:  }
 520:  
 521:  /**
 522:  * Gets the Font of this object.
 523:  * 
 524:  * @return the font for the current node
 525:  */
 526:  public Font getFont()
 527:  {
 528:  return tree.getFont();
 529:  }
 530:  
 531:  /**
 532:  * Gets the FontMetrics of this object.
 533:  * 
 534:  * @param f - the current font.
 535:  * @return the font metrics for the given font.
 536:  */
 537:  public FontMetrics getFontMetrics(Font f)
 538:  {
 539:  return tree.getFontMetrics(f);
 540:  }
 541:  
 542:  /**
 543:  * Get the foreground color of this object.
 544:  * 
 545:  * @return the foreground for this object.
 546:  */
 547:  public Color getForeground()
 548:  {
 549:  return tree.getForeground();
 550:  }
 551:  
 552:  /**
 553:  * Gets the locale of the component.
 554:  * 
 555:  * @return the locale of the component.
 556:  */
 557:  public Locale getLocale()
 558:  {
 559:  return tree.getLocale();
 560:  }
 561:  
 562:  /**
 563:  * Gets the location of the object relative to the 
 564:  * parent in the form of a point specifying the object's 
 565:  * top-left corner in the screen's coordinate space. 
 566:  * 
 567:  * @return the location of the current node.
 568:  */
 569:  public Point getLocation()
 570:  {
 571:  return getLocationInJTree();
 572:  }
 573:  
 574:  /**
 575:  * Returns the location in the tree.
 576:  * 
 577:  * @return the location in the JTree.
 578:  */
 579:  protected Point getLocationInJTree()
 580:  {
 581:  Rectangle bounds = tree.getPathBounds(tp);
 582:  return new Point(bounds.x, bounds.y);
 583:  }
 584:  
 585:  /**
 586:  * Returns the location of the object on the screen.
 587:  * 
 588:  * @return the location of the object on the screen.
 589:  */
 590:  public Point getLocationOnScreen()
 591:  {
 592:  Point loc = getLocation();
 593:  SwingUtilities.convertPointToScreen(loc, tree);
 594:  return loc;
 595:  }
 596:  
 597:  /**
 598:  * Returns the size of this object in the form of a Dimension object.
 599:  * 
 600:  * @return the size of the object
 601:  */
 602:  public Dimension getSize()
 603:  {
 604:  Rectangle b = getBounds();
 605:  return b.getSize();
 606:  }
 607:  
 608:  /**
 609:  * Returns true if the current child of this object is selected.
 610:  * 
 611:  * @param i - the child of the current node
 612:  * @return true if the child is selected.
 613:  */
 614:  public boolean isAccessibleChildSelected(int i)
 615:  {
 616:  Object child = mod.getChild(tp.getLastPathComponent(), i);
 617:  if (child != null)
 618:  return tree.isPathSelected(tp.pathByAddingChild(child));
 619:  return false;
 620:  }
 621:  
 622:  /**
 623:  * Determines if the object is enabled.
 624:  * 
 625:  * @return true if the tree is enabled
 626:  */
 627:  public boolean isEnabled()
 628:  {
 629:  return tree.isEnabled();
 630:  }
 631:  
 632:  /**
 633:  * Returns whether this object can accept focus or not.
 634:  * 
 635:  * @return true, it is always focus traversable
 636:  */
 637:  public boolean isFocusTraversable()
 638:  {
 639:  return true;
 640:  }
 641:  
 642:  /**
 643:  * Determines if the object is showing.
 644:  * 
 645:  * @return true if the object is visible and the
 646:  * parent is visible.
 647:  */
 648:  public boolean isShowing()
 649:  {
 650:  return isVisible() && tree.isShowing();
 651:  }
 652:  
 653:  /**
 654:  * Determines if the object is visible.
 655:  * 
 656:  * @return true if the object is visible.
 657:  */
 658:  public boolean isVisible()
 659:  {
 660:  return tree.isVisible(tp);
 661:  }
 662:  
 663:  /**
 664:  * Removes the specified selected item in the object from the
 665:  * object's selection.
 666:  * 
 667:  * @param i - the specified item to remove
 668:  */
 669:  public void removeAccessibleSelection(int i)
 670:  {
 671:  if (mod != null)
 672:  {
 673:  Object child = mod.getChild(tp.getLastPathComponent(), i);
 674:  if (child != null)
 675:  {
 676:  if (!states.contains(AccessibleState.MULTISELECTABLE))
 677:  clearAccessibleSelection();
 678:  if (selectionList.contains(child))
 679:  {
 680:  selectionList.remove(child); 
 681:  tree.removeSelectionPath(tp.pathByAddingChild(child));
 682:  }
 683:  }
 684:  }
 685:  }
 686:  
 687:  /**
 688:  * Removes the specified focus listener so it no longer receives focus 
 689:  * events from this component.
 690:  * 
 691:  * @param l - the focus listener to remove
 692:  */
 693:  public void removeFocusListener(FocusListener l)
 694:  {
 695:  tree.removeFocusListener(l);
 696:  }
 697:  
 698:  /**
 699:  * Remove a PropertyChangeListener from the listener list.
 700:  * 
 701:  * @param l - the property change listener to remove.
 702:  */
 703:  public void removePropertyChangeListener(PropertyChangeListener l)
 704:  {
 705:  // Nothing to do here.
 706:  }
 707:  
 708:  /**
 709:  * Requests focus for this object.
 710:  */
 711:  public void requestFocus()
 712:  {
 713:  tree.requestFocus();
 714:  }
 715:  
 716:  /**
 717:  * Causes every selected item in the object to be selected if the object 
 718:  * supports multiple selections.
 719:  */
 720:  public void selectAllAccessibleSelection()
 721:  {
 722:  Object parent = tp.getLastPathComponent();
 723:  if (mod != null)
 724:  {
 725:  for (int i = 0; i < mod.getChildCount(parent); i++)
 726:  {
 727:  Object child = mod.getChild(parent, i);
 728:  if (child != null)
 729:  {
 730:  if (!states.contains(AccessibleState.MULTISELECTABLE))
 731:  clearAccessibleSelection();
 732:  if (selectionList.contains(child))
 733:  {
 734:  selectionList.add(child);
 735:  tree.addSelectionPath(tp.pathByAddingChild(child));
 736:  }
 737:  }
 738:  }
 739:  }
 740:  }
 741:  
 742:  /**
 743:  * Set the accessible description of this object.
 744:  * 
 745:  * @param s - the string to set the accessible description to.
 746:  */
 747:  public void setAccessibleDescription(String s)
 748:  {
 749:  super.setAccessibleDescription(s);
 750:  }
 751:  
 752:  /**
 753:  * Set the localized accessible name of this object.
 754:  * 
 755:  * @param s - the string to set the accessible name to.
 756:  */
 757:  public void setAccessibleName(String s)
 758:  {
 759:  super.setAccessibleName(s);
 760:  }
 761:  
 762:  /**
 763:  * Set the background color of this object.
 764:  * 
 765:  * @param c - the color to set the background to.
 766:  */
 767:  public void setBackground(Color c)
 768:  {
 769:  // Nothing to do here.
 770:  }
 771:  
 772:  /**
 773:  * Sets the bounds of this object in the form of a Rectangle object.
 774:  * 
 775:  * @param r - the bounds to set the object o
 776:  */
 777:  public void setBounds(Rectangle r)
 778:  {
 779:  // Nothing to do here.
 780:  }
 781:  
 782:  /**
 783:  * Sets the Cursor of this object.
 784:  * 
 785:  * @param c - the new cursor
 786:  */
 787:  public void setCursor(Cursor c)
 788:  {
 789:  cursor = c;
 790:  }
 791:  
 792:  /**
 793:  * Sets the enabled state of the object.
 794:  * 
 795:  * @param b - boolean to enable or disable object
 796:  */
 797:  public void setEnabled(boolean b)
 798:  {
 799:  // Nothing to do here.
 800:  }
 801:  
 802:  /**
 803:  * Sets the Font of this object.
 804:  * 
 805:  * @param f - the new font.
 806:  */
 807:  public void setFont(Font f)
 808:  {
 809:  // Nothing to do here.
 810:  }
 811:  
 812:  /**
 813:  * Sets the foreground color of this object.
 814:  * 
 815:  * @param c - the new foreground color.
 816:  */
 817:  public void setForeground(Color c)
 818:  {
 819:  // Nothing to do here.
 820:  }
 821:  
 822:  /**
 823:  * Sets the location of the object relative to the parent.
 824:  * 
 825:  * @param p - the new location for the object.
 826:  */
 827:  public void setLocation(Point p)
 828:  {
 829:  // Nothing to do here.
 830:  }
 831:  
 832:  /**
 833:  * Resizes this object so that it has width and height.
 834:  * 
 835:  * @param d - the new size for the object.
 836:  */
 837:  public void setSize(Dimension d)
 838:  {
 839:  // Nothing to do here.
 840:  }
 841:  
 842:  /**
 843:  * Sets the visible state of the object.
 844:  * 
 845:  * @param b - sets the objects visibility.
 846:  */
 847:  public void setVisible(boolean b)
 848:  {
 849:  // Nothing to do here.
 850:  }
 851:  }
 852:  
 853:  /**
 854:  * Constructor
 855:  */
 856:  public AccessibleJTree()
 857:  {
 858:  // Nothing to do here.
 859:  }
 860:  
 861:  /**
 862:  * Adds the specified selected item in the object to the object's selection.
 863:  * 
 864:  * @param i - the row to add to the tree's selection
 865:  */
 866:  public void addAccessibleSelection(int i)
 867:  {
 868:  addSelectionInterval(i, i);
 869:  }
 870:  
 871:  /**
 872:  * Clears the selection in the object, so that nothing in the object is selected.
 873:  */
 874:  public void clearAccessibleSelection()
 875:  {
 876:  clearSelection();
 877:  }
 878:  
 879:  /**
 880:  * Fire a visible data property change notification.
 881:  */
 882:  public void fireVisibleDataPropertyChange()
 883:  {
 884:  treeDidChange();
 885:  }
 886:  
 887:  /**
 888:  * Returns the Accessible child, if one exists, contained at the local 
 889:  * coordinate Point.
 890:  * 
 891:  * @param p - the point of the accessible to get.
 892:  * @return the accessible at point p.
 893:  */
 894:  public Accessible getAccessibleAt(Point p)
 895:  {
 896:  TreePath tp = getClosestPathForLocation(p.x, p.y);
 897:  if (tp != null)
 898:  return new AccessibleJTreeNode(JTree.this, tp, null);
 899:  return null;
 900:  }
 901:  
 902:  /**
 903:  * Return the nth Accessible child of the object.
 904:  * 
 905:  * @param i - the accessible child to get
 906:  * @return the i-th child
 907:  */
 908:  public Accessible getAccessibleChild(int i)
 909:  {
 910:  return null;
 911:  }
 912:  
 913:  /**
 914:  * Returns the number of top-level children nodes of this JTree.
 915:  * 
 916:  * @return the number of top-level children
 917:  */
 918:  public int getAccessibleChildrenCount()
 919:  {
 920:  TreeModel model = getModel();
 921:  if (model != null)
 922:  return model.getChildCount(model.getRoot());
 923:  return 0;
 924:  }
 925:  
 926:  /**
 927:  * Get the index of this object in its accessible parent.
 928:  * 
 929:  * @return the index of this object.
 930:  */
 931:  public int getAccessibleIndexInParent()
 932:  {
 933:  return 0;
 934:  }
 935:  
 936:  /**
 937:  * Get the role of this object.
 938:  * 
 939:  * @return the role of this object
 940:  */
 941:  public AccessibleRole getAccessibleRole()
 942:  {
 943:  return AccessibleRole.TREE;
 944:  }
 945:  
 946:  /**
 947:  * Get the AccessibleSelection associated with this object.
 948:  * 
 949:  * @return the accessible selection of the tree
 950:  */
 951:  public AccessibleSelection getAccessibleSelection()
 952:  {
 953:  TreeModel mod = getModel();
 954:  if (mod != null)
 955:  return (new AccessibleJTreeNode(JTree.this, 
 956:  new TreePath(mod.getRoot()), null)).getAccessibleSelection();
 957:  return null;
 958:  }
 959:  
 960:  /**
 961:  * Returns an Accessible representing the specified selected item in the object.
 962:  * 
 963:  * @return the i-th accessible in the selection
 964:  */
 965:  public Accessible getAccessibleSelection(int i)
 966:  {
 967:  TreeModel mod = getModel();
 968:  if (mod != null)
 969:  return (new AccessibleJTreeNode(JTree.this, 
 970:  new TreePath(mod.getRoot()), null)).getAccessibleSelection(i);
 971:  return null;
 972:  }
 973:  
 974:  /**
 975:  * Returns the number of items currently selected.
 976:  * 
 977:  * @return the number of selected accessibles.
 978:  */
 979:  public int getAccessibleSelectionCount()
 980:  {
 981:  return getSelectionCount();
 982:  }
 983:  
 984:  /**
 985:  * Returns true if the current child of this object is selected.
 986:  * 
 987:  * @param i - the child of this object
 988:  * @return true if the i-th child is selected.
 989:  */
 990:  public boolean isAccessibleChildSelected(int i)
 991:  {
 992:  // Nothing to do here.
 993:  return false;
 994:  }
 995:  
 996:  /**
 997:  * Removes the specified selected item in the object from the object's
 998:  * selection.
 999:  * 
1000:  * @param i - the i-th selected item to remove
1001:  */
1002:  public void removeAccessibleSelection(int i)
1003:  {
1004:  removeSelectionInterval(i, i);
1005:  }
1006:  
1007:  /**
1008:  * Causes every selected item in the object to be selected if the object
1009:  * supports multiple selections.
1010:  */
1011:  public void selectAllAccessibleSelection()
1012:  {
1013:  if (getSelectionModel().getSelectionMode() != 
1014:  TreeSelectionModel.SINGLE_TREE_SELECTION)
1015:  addSelectionInterval(0, getVisibleRowCount());
1016:  }
1017:  
1018:  /**
1019:  * Tree Collapsed notification
1020:  * 
1021:  * @param e - the event
1022:  */
1023:  public void treeCollapsed(TreeExpansionEvent e)
1024:  {
1025:  fireTreeCollapsed(e.getPath());
1026:  }
1027:  
1028:  /**
1029:  * Tree Model Expansion notification.
1030:  * 
1031:  * @param e - the event
1032:  */
1033:  public void treeExpanded(TreeExpansionEvent e)
1034:  {
1035:  fireTreeExpanded(e.getPath());
1036:  }
1037:  
1038:  /**
1039:  * Tree Model Node change notification.
1040:  * 
1041:  * @param e - the event
1042:  */
1043:  public void treeNodesChanged(TreeModelEvent e)
1044:  {
1045:  // Nothing to do here.
1046:  }
1047:  
1048:  /**
1049:  * Tree Model Node change notification.
1050:  * 
1051:  * @param e - the event
1052:  */
1053:  public void treeNodesInserted(TreeModelEvent e)
1054:  {
1055:  // Nothing to do here.
1056:  }
1057:  
1058:  /**
1059:  * Tree Model Node change notification.
1060:  * 
1061:  * @param e - the event
1062:  */
1063:  public void treeNodesRemoved(TreeModelEvent e)
1064:  {
1065:  // Nothing to do here.
1066:  }
1067:  
1068:  /**
1069:  * Tree Model structure change change notification.
1070:  * 
1071:  * @param e - the event
1072:  */
1073:  public void treeStructureChanged(TreeModelEvent e)
1074:  {
1075:  // Nothing to do here.
1076:  }
1077:  
1078:  /**
1079:  * Tree Selection Listener value change method.
1080:  * 
1081:  * @param e - the event
1082:  */
1083:  public void valueChanged(TreeSelectionEvent e)
1084:  {
1085:  fireValueChanged(e);
1086:  }
1087:  }
1088:  
1089:  public static class DynamicUtilTreeNode extends DefaultMutableTreeNode
1090:  {
1091:  protected Object childValue;
1092: 
1093:  protected boolean loadedChildren;
1094: 
1095:  /**
1096:  * Currently not set or used by this class. It might be set and used in
1097:  * later versions of this class.
1098:  */
1099:  protected boolean hasChildren;
1100: 
1101:  public DynamicUtilTreeNode(Object value, Object children)
1102:  {
1103:  super(value);
1104:  childValue = children;
1105:  loadedChildren = false;
1106:  }
1107: 
1108:  public int getChildCount()
1109:  {
1110:  loadChildren();
1111:  return super.getChildCount();
1112:  }
1113: 
1114:  protected void loadChildren()
1115:  {
1116:  if (!loadedChildren)
1117:  {
1118:  createChildren(this, childValue);
1119:  loadedChildren = true;
1120:  }
1121:  }
1122: 
1123:  public Enumeration children()
1124:  {
1125:  loadChildren();
1126:  return super.children();
1127:  }
1128: 
1129:  /**
1130:  * Returns the child node at position <code>pos</code>. Subclassed
1131:  * here to load the children if necessary.
1132:  * 
1133:  * @param pos the position of the child node to fetch
1134:  * 
1135:  * @return the childnode at the specified position
1136:  */
1137:  public TreeNode getChildAt(int pos)
1138:  {
1139:  loadChildren();
1140:  return super.getChildAt(pos);
1141:  }
1142: 
1143:  public boolean isLeaf()
1144:  {
1145:  return childValue == null || !(childValue instanceof Hashtable
1146:  || childValue instanceof Vector 
1147:  || childValue.getClass().isArray());
1148:  }
1149: 
1150:  public static void createChildren(DefaultMutableTreeNode parent,
1151:  Object children)
1152:  {
1153:  if (children instanceof Hashtable)
1154:  {
1155:  Hashtable tab = (Hashtable) children;
1156:  Enumeration e = tab.keys();
1157:  while (e.hasMoreElements())
1158:  {
1159:  Object key = e.nextElement();
1160:  Object val = tab.get(key);
1161:  parent.add(new DynamicUtilTreeNode(key, val));
1162:  }
1163:  }
1164:  else if (children instanceof Vector)
1165:  {
1166:  Iterator i = ((Vector) children).iterator();
1167:  while (i.hasNext())
1168:  {
1169:  Object n = i.next();
1170:  parent.add(new DynamicUtilTreeNode(n, n));
1171:  }
1172:  }
1173:  else if (children != null && children.getClass().isArray())
1174:  {
1175:  Object[] arr = (Object[]) children;
1176:  for (int i = 0; i < arr.length; ++i)
1177:  parent.add(new DynamicUtilTreeNode(arr[i], arr[i]));
1178:  }
1179:  }
1180:  }
1181: 
1182:  /**
1183:  * Listens to the model of the JTree and updates the property 
1184:  * <code>expandedState</code> if nodes are removed or changed.
1185:  */
1186:  protected class TreeModelHandler implements TreeModelListener
1187:  {
1188: 
1189:  /**
1190:  * Creates a new instance of TreeModelHandler.
1191:  */
1192:  protected TreeModelHandler()
1193:  {
1194:  // Nothing to do here.
1195:  }
1196: 
1197:  /**
1198:  * Notifies when a node has changed in some ways. This does not include
1199:  * that a node has changed its location or changed it's children. It
1200:  * only means that some attributes of the node have changed that might
1201:  * affect its presentation.
1202:  * 
1203:  * This method is called after the actual change occured.
1204:  * 
1205:  * @param ev the TreeModelEvent describing the change
1206:  */
1207:  public void treeNodesChanged(TreeModelEvent ev)
1208:  {
1209:  // Nothing to do here.
1210:  }
1211: 
1212:  /**
1213:  * Notifies when a node is inserted into the tree.
1214:  * 
1215:  * This method is called after the actual change occured.
1216:  * 
1217:  * @param ev the TreeModelEvent describing the change
1218:  */
1219:  public void treeNodesInserted(TreeModelEvent ev)
1220:  {
1221:  // nothing to do here
1222:  }
1223: 
1224:  /**
1225:  * Notifies when a node is removed from the tree.
1226:  * 
1227:  * This method is called after the actual change occured.
1228:  *
1229:  * @param ev the TreeModelEvent describing the change
1230:  */
1231:  public void treeNodesRemoved(TreeModelEvent ev)
1232:  {
1233:  if (ev != null)
1234:  {
1235:  TreePath parent = ev.getTreePath();
1236:  Object[] children = ev.getChildren();
1237:  TreeSelectionModel sm = getSelectionModel();
1238:  if (children != null)
1239:  {
1240:  TreePath path;
1241:  Vector toRemove = new Vector();
1242:  // Collect items that we must remove.
1243:  for (int i = children.length - 1; i >= 0; i--)
1244:  {
1245:  path = parent.pathByAddingChild(children[i]);
1246:  if (nodeStates.containsKey(path))
1247:  toRemove.add(path);
1248:  // Clear selection while we are at it.
1249:  if (sm != null)
1250:  removeDescendantSelectedPaths(path, true);
1251:  }
1252:  if (toRemove.size() > 0)
1253:  removeDescendantToggledPaths(toRemove.elements());
1254:  TreeModel model = getModel();
1255:  if (model == null || model.isLeaf(parent.getLastPathComponent()))
1256:  nodeStates.remove(parent);
1257:  }
1258:  }
1259:  }
1260: 
1261:  /**
1262:  * Notifies when the structure of the tree is changed.
1263:  * 
1264:  * This method is called after the actual change occured.
1265:  * 
1266:  * @param ev the TreeModelEvent describing the change
1267:  */
1268:  public void treeStructureChanged(TreeModelEvent ev)
1269:  {
1270:  if (ev != null)
1271:  {
1272:  TreePath parent = ev.getTreePath();
1273:  if (parent != null)
1274:  {
1275:  if (parent.getPathCount() == 1)
1276:  {
1277:  // We have a new root, clear everything.
1278:  clearToggledPaths();
1279:  Object root = treeModel.getRoot();
1280:  if (root != null && treeModel.isLeaf(root))
1281:  nodeStates.put(parent, Boolean.TRUE);
1282:  }
1283:  else if (nodeStates.containsKey(parent))
1284:  {
1285:  Vector toRemove = new Vector();
1286:  boolean expanded = isExpanded(parent);
1287:  toRemove.add(parent);
1288:  removeDescendantToggledPaths(toRemove.elements());
1289:  if (expanded)
1290:  {
1291:  TreeModel model = getModel();
1292:  if (model != null
1293:  || model.isLeaf(parent.getLastPathComponent()))
1294:  collapsePath(parent);
1295:  else
1296:  nodeStates.put(parent, Boolean.TRUE);
1297:  }
1298:  }
1299:  removeDescendantSelectedPaths(parent, false);
1300:  }
1301:  }
1302:  }
1303:  }
1304: 
1305:  /**
1306:  * This redirects TreeSelectionEvents and rewrites the source of it to be
1307:  * this JTree. This is typically done when the tree model generates an
1308:  * event, but the JTree object associated with that model should be listed
1309:  * as the actual source of the event.
1310:  */
1311:  protected class TreeSelectionRedirector implements TreeSelectionListener,
1312:  Serializable
1313:  {
1314:  /** The serial version UID. */
1315:  private static final long serialVersionUID = -3505069663646241664L;
1316: 
1317:  /**
1318:  * Creates a new instance of TreeSelectionRedirector
1319:  */
1320:  protected TreeSelectionRedirector()
1321:  {
1322:  // Nothing to do here.
1323:  }
1324: 
1325:  /**
1326:  * Notifies when the tree selection changes.
1327:  * 
1328:  * @param ev the TreeSelectionEvent that describes the change
1329:  */
1330:  public void valueChanged(TreeSelectionEvent ev)
1331:  {
1332:  TreeSelectionEvent rewritten = 
1333:  (TreeSelectionEvent) ev.cloneWithSource(JTree.this);
1334:  fireValueChanged(rewritten);
1335:  }
1336:  }
1337: 
1338:  /**
1339:  * A TreeModel that does not allow anything to be selected.
1340:  */
1341:  protected static class EmptySelectionModel extends DefaultTreeSelectionModel
1342:  {
1343:  /** The serial version UID. */
1344:  private static final long serialVersionUID = -5815023306225701477L;
1345: 
1346:  /**
1347:  * The shared instance of this model.
1348:  */
1349:  protected static final EmptySelectionModel sharedInstance =
1350:  new EmptySelectionModel();
1351: 
1352:  /**
1353:  * Creates a new instance of EmptySelectionModel.
1354:  */
1355:  protected EmptySelectionModel()
1356:  {
1357:  // Nothing to do here.
1358:  }
1359: 
1360:  /**
1361:  * Returns the shared instance of EmptySelectionModel.
1362:  * 
1363:  * @return the shared instance of EmptySelectionModel
1364:  */
1365:  public static EmptySelectionModel sharedInstance()
1366:  {
1367:  return sharedInstance;
1368:  }
1369: 
1370:  /**
1371:  * This catches attempts to set a selection and sets nothing instead.
1372:  * 
1373:  * @param paths not used here
1374:  */
1375:  public void setSelectionPaths(TreePath[] paths)
1376:  {
1377:  // We don't allow selections in this class.
1378:  }
1379: 
1380:  /**
1381:  * This catches attempts to add something to the selection.
1382:  * 
1383:  * @param paths not used here
1384:  */
1385:  public void addSelectionPaths(TreePath[] paths)
1386:  {
1387:  // We don't allow selections in this class.
1388:  }
1389: 
1390:  /**
1391:  * This catches attempts to remove something from the selection.
1392:  * 
1393:  * @param paths not used here
1394:  */
1395:  public void removeSelectionPaths(TreePath[] paths)
1396:  {
1397:  // We don't allow selections in this class.
1398:  }
1399:  }
1400: 
1401:  private static final long serialVersionUID = 7559816092864483649L;
1402: 
1403:  public static final String CELL_EDITOR_PROPERTY = "cellEditor";
1404: 
1405:  public static final String CELL_RENDERER_PROPERTY = "cellRenderer";
1406: 
1407:  public static final String EDITABLE_PROPERTY = "editable";
1408: 
1409:  public static final String INVOKES_STOP_CELL_EDITING_PROPERTY =
1410:  "invokesStopCellEditing";
1411: 
1412:  public static final String LARGE_MODEL_PROPERTY = "largeModel";
1413: 
1414:  public static final String ROOT_VISIBLE_PROPERTY = "rootVisible";
1415: 
1416:  public static final String ROW_HEIGHT_PROPERTY = "rowHeight";
1417: 
1418:  public static final String SCROLLS_ON_EXPAND_PROPERTY = "scrollsOnExpand";
1419: 
1420:  public static final String SELECTION_MODEL_PROPERTY = "selectionModel";
1421: 
1422:  public static final String SHOWS_ROOT_HANDLES_PROPERTY = "showsRootHandles";
1423: 
1424:  public static final String TOGGLE_CLICK_COUNT_PROPERTY = "toggleClickCount";
1425: 
1426:  public static final String TREE_MODEL_PROPERTY = "model";
1427: 
1428:  public static final String VISIBLE_ROW_COUNT_PROPERTY = "visibleRowCount";
1429: 
1430:  /** @since 1.3 */
1431:  public static final String ANCHOR_SELECTION_PATH_PROPERTY =
1432:  "anchorSelectionPath";
1433: 
1434:  /** @since 1.3 */
1435:  public static final String LEAD_SELECTION_PATH_PROPERTY = "leadSelectionPath";
1436: 
1437:  /** @since 1.3 */
1438:  public static final String EXPANDS_SELECTED_PATHS_PROPERTY =
1439:  "expandsSelectedPaths";
1440: 
1441:  private static final Object EXPANDED = Boolean.TRUE;
1442: 
1443:  private static final Object COLLAPSED = Boolean.FALSE;
1444: 
1445:  private boolean dragEnabled;
1446: 
1447:  private boolean expandsSelectedPaths;
1448: 
1449:  private TreePath anchorSelectionPath;
1450: 
1451:  /**
1452:  * This contains the state of all nodes in the tree. Al/ entries map the
1453:  * TreePath of a note to to its state. Valid states are EXPANDED and
1454:  * COLLAPSED. Nodes not in this Hashtable are assumed state COLLAPSED.
1455:  *
1456:  * This is package private to avoid accessor methods.
1457:  */
1458:  Hashtable nodeStates = new Hashtable();
1459: 
1460:  protected transient TreeCellEditor cellEditor;
1461: 
1462:  protected transient TreeCellRenderer cellRenderer;
1463: 
1464:  protected boolean editable;
1465: 
1466:  protected boolean invokesStopCellEditing;
1467: 
1468:  protected boolean largeModel;
1469: 
1470:  protected boolean rootVisible;
1471: 
1472:  protected int rowHeight;
1473: 
1474:  protected boolean scrollsOnExpand;
1475: 
1476:  protected transient TreeSelectionModel selectionModel;
1477: 
1478:  protected boolean showsRootHandles;
1479: 
1480:  protected int toggleClickCount;
1481: 
1482:  protected transient TreeModel treeModel;
1483: 
1484:  protected int visibleRowCount;
1485: 
1486:  /**
1487:  * Handles TreeModelEvents to update the expandedState.
1488:  */
1489:  protected transient TreeModelListener treeModelListener;
1490: 
1491:  /**
1492:  * Redirects TreeSelectionEvents so that the source is this JTree.
1493:  */
1494:  protected TreeSelectionRedirector selectionRedirector =
1495:  new TreeSelectionRedirector();
1496: 
1497:  /**
1498:  * Indicates if the rowHeight property has been set by a client
1499:  * program or by the UI.
1500:  *
1501:  * @see #setUIProperty(String, Object)
1502:  * @see LookAndFeel#installProperty(JComponent, String, Object)
1503:  */
1504:  private boolean clientRowHeightSet = false;
1505: 
1506:  /**
1507:  * Indicates if the scrollsOnExpand property has been set by a client
1508:  * program or by the UI.
1509:  *
1510:  * @see #setUIProperty(String, Object)
1511:  * @see LookAndFeel#installProperty(JComponent, String, Object)
1512:  */
1513:  private boolean clientScrollsOnExpandSet = false;
1514: 
1515:  /**
1516:  * Indicates if the showsRootHandles property has been set by a client
1517:  * program or by the UI.
1518:  *
1519:  * @see #setUIProperty(String, Object)
1520:  * @see LookAndFeel#installProperty(JComponent, String, Object)
1521:  */
1522:  private boolean clientShowsRootHandlesSet = false;
1523: 
1524:  /**
1525:  * Creates a new <code>JTree</code> object.
1526:  */
1527:  public JTree()
1528:  {
1529:  this(getDefaultTreeModel());
1530:  }
1531: 
1532:  /**
1533:  * Creates a new <code>JTree</code> object.
1534:  * 
1535:  * @param value the initial nodes in the tree
1536:  */
1537:  public JTree(Hashtable<?, ?> value)
1538:  {
1539:  this(createTreeModel(value));
1540:  }
1541: 
1542:  /**
1543:  * Creates a new <code>JTree</code> object.
1544:  * 
1545:  * @param value the initial nodes in the tree
1546:  */
1547:  public JTree(Object[] value)
1548:  {
1549:  this(createTreeModel(value));
1550:  }
1551: 
1552:  /**
1553:  * Creates a new <code>JTree</code> object.
1554:  * 
1555:  * @param model the model to use
1556:  */
1557:  public JTree(TreeModel model)
1558:  {
1559:  setRootVisible(true);
1560:  setSelectionModel( new DefaultTreeSelectionModel() );
1561:  
1562:  // The root node appears expanded by default.
1563:  nodeStates = new Hashtable();
1564: 
1565:  // The cell renderer gets set by the UI.
1566:  cellRenderer = null;
1567: 
1568:  // Install the UI before installing the model. This way we avoid double
1569:  // initialization of lots of UI and model stuff inside the UI and related
1570:  // classes. The necessary UI updates are performed via property change
1571:  // events to the UI.
1572:  updateUI();
1573:  setModel(model);
1574:  }
1575: 
1576:  /**
1577:  * Creates a new <code>JTree</code> object.
1578:  * 
1579:  * @param root the root node
1580:  */
1581:  public JTree(TreeNode root)
1582:  {
1583:  this(root, false);
1584:  }
1585: 
1586:  /**
1587:  * Creates a new <code>JTree</code> object.
1588:  * 
1589:  * @param root the root node
1590:  * @param asksAllowChildren if false, all nodes without children are leaf
1591:  * nodes. If true, only nodes that do not allow children are leaf
1592:  * nodes.
1593:  */
1594:  public JTree(TreeNode root, boolean asksAllowChildren)
1595:  {
1596:  this(new DefaultTreeModel(root, asksAllowChildren));
1597:  }
1598: 
1599:  /**
1600:  * Creates a new <code>JTree</code> object.
1601:  * 
1602:  * @param value the initial nodes in the tree
1603:  */
1604:  public JTree(Vector<?> value)
1605:  {
1606:  this(createTreeModel(value));
1607:  }
1608: 
1609:  public int getRowForPath(TreePath path)
1610:  {
1611:  TreeUI ui = getUI();
1612: 
1613:  if (ui != null)
1614:  return ui.getRowForPath(this, path);
1615: 
1616:  return -1;
1617:  }
1618: 
1619:  public TreePath getPathForRow(int row)
1620:  {
1621:  TreeUI ui = getUI();
1622:  return ui != null ? ui.getPathForRow(this, row) : null;
1623:  }
1624:  
1625:  /**
1626:  * Get the pathes that are displayes between the two given rows.
1627:  * 
1628:  * @param index0 the starting row, inclusive
1629:  * @param index1 the ending row, inclusive
1630:  * 
1631:  * @return the array of the tree pathes
1632:  */
1633:  protected TreePath[] getPathBetweenRows(int index0, int index1)
1634:  {
1635:  TreeUI ui = getUI();
1636: 
1637:  if (ui == null)
1638:  return null;
1639: 
1640:  int minIndex = Math.min(index0, index1);
1641:  int maxIndex = Math.max(index0, index1);
1642:  TreePath[] paths = new TreePath[maxIndex - minIndex + 1];
1643: 
1644:  for (int i = minIndex; i <= maxIndex; ++i)
1645:  paths[i - minIndex] = ui.getPathForRow(this, i);
1646: 
1647:  return paths;
1648:  }
1649: 
1650:  /**
1651:  * Creates a new <code>TreeModel</code> object.
1652:  * 
1653:  * @param value the values stored in the model
1654:  */
1655:  protected static TreeModel createTreeModel(Object value)
1656:  {
1657:  return new DefaultTreeModel(new DynamicUtilTreeNode(value, value));
1658:  }
1659: 
1660:  /**
1661:  * Return the UI associated with this <code>JTree</code> object.
1662:  * 
1663:  * @return the associated <code>TreeUI</code> object
1664:  */
1665:  public TreeUI getUI()
1666:  {
1667:  return (TreeUI) ui;
1668:  }
1669: 
1670:  /**
1671:  * Sets the UI associated with this <code>JTree</code> object.
1672:  * 
1673:  * @param ui the <code>TreeUI</code> to associate
1674:  */
1675:  public void setUI(TreeUI ui)
1676:  {
1677:  super.setUI(ui);
1678:  }
1679: 
1680:  /**
1681:  * This method resets the UI used to the Look and Feel defaults..
1682:  */
1683:  public void updateUI()
1684:  {
1685:  setUI((TreeUI) UIManager.getUI(this));
1686:  }
1687: 
1688:  /**
1689:  * This method returns the String ID of the UI class of Separator.
1690:  * 
1691:  * @return The UI class' String ID.
1692:  */
1693:  public String getUIClassID()
1694:  {
1695:  return "TreeUI";
1696:  }
1697: 
1698:  /**
1699:  * Gets the AccessibleContext associated with this
1700:  * <code>JTree</code>.
1701:  * 
1702:  * @return the associated context
1703:  */
1704:  public AccessibleContext getAccessibleContext()
1705:  {
1706:  return new AccessibleJTree();
1707:  }
1708: 
1709:  /**
1710:  * Returns the preferred viewport size.
1711:  * 
1712:  * @return the preferred size
1713:  */
1714:  public Dimension getPreferredScrollableViewportSize()
1715:  {
1716:  return getPreferredSize();
1717:  }
1718:  
1719:  /**
1720:  * Return the preferred scrolling amount (in pixels) for the given scrolling
1721:  * direction and orientation. This method handles a partially exposed row by
1722:  * returning the distance required to completely expose the item.
1723:  * 
1724:  * @param visibleRect the currently visible part of the component.
1725:  * @param orientation the scrolling orientation
1726:  * @param direction the scrolling direction (negative - up, positive -down).
1727:  * The values greater than one means that more mouse wheel or similar
1728:  * events were generated, and hence it is better to scroll the longer
1729:  * distance.
1730:  * @author Audrius Meskauskas (audriusa@bioinformatics.org)
1731:  */
1732:  public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
1733:  int direction)
1734:  {
1735:  int delta = 0;
1736: 
1737:  // Round so that the top would start from the row boundary
1738:  if (orientation == SwingConstants.VERTICAL)
1739:  {
1740:  int row = getClosestRowForLocation(0, visibleRect.y);
1741:  if (row != -1)
1742:  {
1743:  Rectangle b = getRowBounds(row);
1744:  if (b.y != visibleRect.y)
1745:  {
1746:  if (direction < 0)
1747:  delta = Math.max(0, visibleRect.y - b.y);
1748:  else
1749:  delta = b.y + b.height - visibleRect.y;
1750:  }
1751:  else
1752:  {
1753:  if (direction < 0)
1754:  {
1755:  if (row != 0)
1756:  {
1757:  b = getRowBounds(row - 1);
1758:  delta = b.height;
1759:  }
1760:  }
1761:  else
1762:  delta = b.height;
1763:  }
1764:  }
1765:  }
1766:  else
1767:  // The RI always returns 4 for HORIZONTAL scrolling.
1768:  delta = 4;
1769:  return delta;
1770:  }
1771: 
1772:  public int getScrollableBlockIncrement(Rectangle visibleRect,
1773:  int orientation, int direction)
1774:  {
1775:  int block;
1776:  if (orientation == SwingConstants.VERTICAL)
1777:  block = visibleRect.height;
1778:  else
1779:  block = visibleRect.width;
1780:  return block;
1781:  }
1782: 
1783:  public boolean getScrollableTracksViewportHeight()
1784:  {
1785:  if (getParent() instanceof JViewport)
1786:  return ((JViewport) getParent()).getHeight() > getPreferredSize().height;
1787:  return false;
1788:  }
1789: 
1790:  public boolean getScrollableTracksViewportWidth()
1791:  {
1792:  if (getParent() instanceof JViewport)
1793:  return ((JViewport) getParent()).getWidth() > getPreferredSize().width;
1794:  return false;
1795:  }
1796: 
1797:  /**
1798:  * Adds a <code>TreeExpansionListener</code> object to the tree.
1799:  * 
1800:  * @param listener the listener to add
1801:  */
1802:  public void addTreeExpansionListener(TreeExpansionListener listener)
1803:  {
1804:  listenerList.add(TreeExpansionListener.class, listener);
1805:  }
1806: 
1807:  /**
1808:  * Removes a <code>TreeExpansionListener</code> object from the tree.
1809:  * 
1810:  * @param listener the listener to remove
1811:  */
1812:  public void removeTreeExpansionListener(TreeExpansionListener listener)
1813:  {
1814:  listenerList.remove(TreeExpansionListener.class, listener);
1815:  }
1816: 
1817:  /**
1818:  * Returns all added <code>TreeExpansionListener</code> objects.
1819:  * 
1820:  * @return an array of listeners
1821:  */
1822:  public TreeExpansionListener[] getTreeExpansionListeners()
1823:  {
1824:  return (TreeExpansionListener[]) getListeners(TreeExpansionListener.class);
1825:  }
1826: 
1827:  /**
1828:  * Notifies all listeners that the tree was collapsed.
1829:  * 
1830:  * @param path the path to the node that was collapsed
1831:  */
1832:  public void fireTreeCollapsed(TreePath path)
1833:  {
1834:  TreeExpansionEvent event = new TreeExpansionEvent(this, path);
1835:  TreeExpansionListener[] listeners = getTreeExpansionListeners();
1836: 
1837:  for (int index = 0; index < listeners.length; ++index)
1838:  listeners[index].treeCollapsed(event);
1839:  }
1840: 
1841:  /**
1842:  * Notifies all listeners that the tree was expanded.
1843:  * 
1844:  * @param path the path to the node that was expanded
1845:  */
1846:  public void fireTreeExpanded(TreePath path)
1847:  {
1848:  TreeExpansionEvent event = new TreeExpansionEvent(this, path);
1849:  TreeExpansionListener[] listeners = getTreeExpansionListeners();
1850: 
1851:  for (int index = 0; index < listeners.length; ++index)
1852:  listeners[index].treeExpanded(event);
1853:  }
1854: 
1855:  /**
1856:  * Adds a <code>TreeSelctionListener</code> object to the tree.
1857:  * 
1858:  * @param listener the listener to add
1859:  */
1860:  public void addTreeSelectionListener(TreeSelectionListener listener)
1861:  {
1862:  listenerList.add(TreeSelectionListener.class, listener);
1863:  }
1864: 
1865:  /**
1866:  * Removes a <code>TreeSelectionListener</code> object from the tree.
1867:  * 
1868:  * @param listener the listener to remove
1869:  */
1870:  public void removeTreeSelectionListener(TreeSelectionListener listener)
1871:  {
1872:  listenerList.remove(TreeSelectionListener.class, listener);
1873:  }
1874: 
1875:  /**
1876:  * Returns all added <code>TreeSelectionListener</code> objects.
1877:  * 
1878:  * @return an array of listeners
1879:  */
1880:  public TreeSelectionListener[] getTreeSelectionListeners()
1881:  {
1882:  return (TreeSelectionListener[]) 
1883:  getListeners(TreeSelectionListener.class);
1884:  }
1885: 
1886:  /**
1887:  * Notifies all listeners when the selection of the tree changed.
1888:  * 
1889:  * @param event the event to send
1890:  */
1891:  protected void fireValueChanged(TreeSelectionEvent event)
1892:  {
1893:  TreeSelectionListener[] listeners = getTreeSelectionListeners();
1894: 
1895:  for (int index = 0; index < listeners.length; ++index)
1896:  listeners[index].valueChanged(event);
1897:  }
1898: 
1899:  /**
1900:  * Adds a <code>TreeWillExpandListener</code> object to the tree.
1901:  * 
1902:  * @param listener the listener to add
1903:  */
1904:  public void addTreeWillExpandListener(TreeWillExpandListener listener)
1905:  {
1906:  listenerList.add(TreeWillExpandListener.class, listener);
1907:  }
1908: 
1909:  /**
1910:  * Removes a <code>TreeWillExpandListener</code> object from the tree.
1911:  * 
1912:  * @param listener the listener to remove
1913:  */
1914:  public void removeTreeWillExpandListener(TreeWillExpandListener listener)
1915:  {
1916:  listenerList.remove(TreeWillExpandListener.class, listener);
1917:  }
1918: 
1919:  /**
1920:  * Returns all added <code>TreeWillExpandListener</code> objects.
1921:  * 
1922:  * @return an array of listeners
1923:  */
1924:  public TreeWillExpandListener[] getTreeWillExpandListeners()
1925:  {
1926:  return (TreeWillExpandListener[]) 
1927:  getListeners(TreeWillExpandListener.class);
1928:  }
1929: 
1930:  /**
1931:  * Notifies all listeners that the tree will collapse.
1932:  * 
1933:  * @param path the path to the node that will collapse
1934:  */
1935:  public void fireTreeWillCollapse(TreePath path) throws ExpandVetoException
1936:  {
1937:  TreeExpansionEvent event = new TreeExpansionEvent(this, path);
1938:  TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
1939: 
1940:  for (int index = 0; index < listeners.length; ++index)
1941:  listeners[index].treeWillCollapse(event);
1942:  }
1943: 
1944:  /**
1945:  * Notifies all listeners that the tree will expand.
1946:  * 
1947:  * @param path the path to the node that will expand
1948:  */
1949:  public void fireTreeWillExpand(TreePath path) throws ExpandVetoException
1950:  {
1951:  TreeExpansionEvent event = new TreeExpansionEvent(this, path);
1952:  TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
1953: 
1954:  for (int index = 0; index < listeners.length; ++index)
1955:  listeners[index].treeWillExpand(event);
1956:  }
1957: 
1958:  /**
1959:  * Returns the model of this <code>JTree</code> object.
1960:  * 
1961:  * @return the associated <code>TreeModel</code>
1962:  */
1963:  public TreeModel getModel()
1964:  {
1965:  return treeModel;
1966:  }
1967: 
1968:  /**
1969:  * Sets the model to use in <code>JTree</code>.
1970:  * 
1971:  * @param model the <code>TreeModel</code> to use
1972:  */
1973:  public void setModel(TreeModel model)
1974:  {
1975:  if (treeModel == model)
1976:  return;
1977: 
1978:  // Remove listeners from old model.
1979:  if (treeModel != null && treeModelListener != null)
1980:  treeModel.removeTreeModelListener(treeModelListener);
1981: 
1982:  // add treeModelListener to the new model
1983:  if (treeModelListener == null)
1984:  treeModelListener = createTreeModelListener();
1985:  if (model != null) // as setModel(null) is allowed
1986:  model.addTreeModelListener(treeModelListener);
1987: 
1988:  TreeModel oldValue = treeModel;
1989:  treeModel = model;
1990:  clearToggledPaths();
1991: 
1992:  if (treeModel != null)
1993:  {
1994:  if (treeModelListener == null)
1995:  treeModelListener = createTreeModelListener();
1996:  if (treeModelListener != null)
1997:  treeModel.addTreeModelListener(treeModelListener);
1998:  Object root = treeModel.getRoot();
1999:  if (root != null && !treeModel.isLeaf(root))
2000:  {
2001:  nodeStates.put(new TreePath(root), Boolean.TRUE);
2002:  }
2003:  }
2004: 
2005:  firePropertyChange(TREE_MODEL_PROPERTY, oldValue, model);
2006:  }
2007: 
2008:  /**
2009:  * Checks if this <code>JTree</code> object is editable.
2010:  * 
2011:  * @return <code>true</code> if this tree object is editable,
2012:  * <code>false</code> otherwise
2013:  */
2014:  public boolean isEditable()
2015:  {
2016:  return editable;
2017:  }
2018: 
2019:  /**
2020:  * Sets the <code>editable</code> property.
2021:  * 
2022:  * @param flag <code>true</code> to make this tree object editable,
2023:  * <code>false</code> otherwise
2024:  */
2025:  public void setEditable(boolean flag)
2026:  {
2027:  if (editable == flag)
2028:  return;
2029: 
2030:  boolean oldValue = editable;
2031:  editable = flag;
2032:  firePropertyChange(EDITABLE_PROPERTY, oldValue, editable);
2033:  }
2034: 
2035:  /**
2036:  * Checks if the root element is visible.
2037:  * 
2038:  * @return <code>true</code> if the root element is visible,
2039:  * <code>false</code> otherwise
2040:  */
2041:  public boolean isRootVisible()
2042:  {
2043:  return rootVisible;
2044:  }
2045: 
2046:  public void setRootVisible(boolean flag)
2047:  {
2048:  if (rootVisible == flag)
2049:  return;
2050: 
2051:  // If the root is currently selected, unselect it
2052:  if (rootVisible && !flag)
2053:  {
2054:  TreeSelectionModel model = getSelectionModel();
2055:  // The root is always shown in the first row
2056:  TreePath rootPath = getPathForRow(0);
2057:  model.removeSelectionPath(rootPath);
2058:  }
2059:  
2060:  boolean oldValue = rootVisible;
2061:  rootVisible = flag;
2062:  firePropertyChange(ROOT_VISIBLE_PROPERTY, oldValue, flag);
2063:  
2064:  }
2065: 
2066:  public boolean getShowsRootHandles()
2067:  {
2068:  return showsRootHandles;
2069:  }
2070: 
2071:  public void setShowsRootHandles(boolean flag)
2072:  {
2073:  clientShowsRootHandlesSet = true;
2074: 
2075:  if (showsRootHandles == flag)
2076:  return;
2077:  
2078:  boolean oldValue = showsRootHandles;
2079:  showsRootHandles = flag;
2080:  firePropertyChange(SHOWS_ROOT_HANDLES_PROPERTY, oldValue, flag);
2081:  }
2082: 
2083:  public TreeCellEditor getCellEditor()
2084:  {
2085:  return cellEditor;
2086:  }
2087: 
2088:  public void setCellEditor(TreeCellEditor editor)
2089:  {
2090:  if (cellEditor == editor)
2091:  return;
2092: 
2093:  TreeCellEditor oldValue = cellEditor;
2094:  cellEditor = editor;
2095:  firePropertyChange(CELL_EDITOR_PROPERTY, oldValue, editor);
2096:  }
2097: 
2098:  public TreeCellRenderer getCellRenderer()
2099:  {
2100:  return cellRenderer;
2101:  }
2102: 
2103:  public void setCellRenderer(TreeCellRenderer newRenderer)
2104:  {
2105:  if (cellRenderer == newRenderer)
2106:  return;
2107: 
2108:  TreeCellRenderer oldValue = cellRenderer;
2109:  cellRenderer = newRenderer;
2110:  firePropertyChange(CELL_RENDERER_PROPERTY, oldValue, newRenderer);
2111:  }
2112: 
2113:  public TreeSelectionModel getSelectionModel()
2114:  {
2115:  return selectionModel;
2116:  }
2117: 
2118:  public void setSelectionModel(TreeSelectionModel model)
2119:  {
2120:  if (selectionModel == model)
2121:  return;
2122: 
2123:  if( model == null )
2124:  model = EmptySelectionModel.sharedInstance();
2125: 
2126:  if (selectionModel != null)
2127:  selectionModel.removeTreeSelectionListener(selectionRedirector);
2128: 
2129:  TreeSelectionModel oldValue = selectionModel;
2130:  selectionModel = model;
2131: 
2132:  selectionModel.addTreeSelectionListener(selectionRedirector);
2133: 
2134:  firePropertyChange(SELECTION_MODEL_PROPERTY, oldValue, model);
2135:  revalidate();
2136:  repaint();
2137:  }
2138: 
2139:  public int getVisibleRowCount()
2140:  {
2141:  return visibleRowCount;
2142:  }
2143: 
2144:  public void setVisibleRowCount(int rows)
2145:  {
2146:  if (visibleRowCount == rows)
2147:  return;
2148: 
2149:  int oldValue = visibleRowCount;
2150:  visibleRowCount = rows;
2151:  firePropertyChange(VISIBLE_ROW_COUNT_PROPERTY, oldValue, rows);
2152:  }
2153: 
2154:  public boolean isLargeModel()
2155:  {
2156:  return largeModel;
2157:  }
2158: 
2159:  public void setLargeModel(boolean large)
2160:  {
2161:  if (largeModel == large)
2162:  return;
2163: 
2164:  boolean oldValue = largeModel;
2165:  largeModel = large;
2166:  firePropertyChange(LARGE_MODEL_PROPERTY, oldValue, large);
2167:  }
2168: 
2169:  public int getRowHeight()
2170:  {
2171:  return rowHeight;
2172:  }
2173: 
2174:  public void setRowHeight(int height)
2175:  {
2176:  clientRowHeightSet = true;
2177: 
2178:  if (rowHeight == height)
2179:  return;
2180: 
2181:  int oldValue = rowHeight;
2182:  rowHeight = height;
2183:  firePropertyChange(ROW_HEIGHT_PROPERTY, oldValue, height);
2184:  }
2185: 
2186:  public boolean isFixedRowHeight()
2187:  {
2188:  return rowHeight > 0;
2189:  }
2190: 
2191:  public boolean getInvokesStopCellEditing()
2192:  {
2193:  return invokesStopCellEditing;
2194:  }
2195: 
2196:  public void setInvokesStopCellEditing(boolean invoke)
2197:  {
2198:  if (invokesStopCellEditing == invoke)
2199:  return;
2200: 
2201:  boolean oldValue = invokesStopCellEditing;
2202:  invokesStopCellEditing = invoke;
2203:  firePropertyChange(INVOKES_STOP_CELL_EDITING_PROPERTY, 
2204:  oldValue, invoke);
2205:  }
2206: 
2207:  /**
2208:  * @since 1.3
2209:  */
2210:  public int getToggleClickCount()
2211:  {
2212:  return toggleClickCount;
2213:  }
2214: 
2215:  /**
2216:  * @since 1.3
2217:  */
2218:  public void setToggleClickCount(int count)
2219:  {
2220:  if (toggleClickCount == count)
2221:  return;
2222: 
2223:  int oldValue = toggleClickCount;
2224:  toggleClickCount = count;
2225:  firePropertyChange(TOGGLE_CLICK_COUNT_PROPERTY, oldValue, count);
2226:  }
2227: 
2228:  public void scrollPathToVisible(TreePath path)
2229:  {
2230:  if (path == null)
2231:  return;
2232:  Rectangle rect = getPathBounds(path);
2233:  scrollRectToVisible(rect);
2234:  }
2235: 
2236:  public void scrollRowToVisible(int row)
2237:  {
2238:  scrollPathToVisible(getPathForRow(row));
2239:  }
2240: 
2241:  public boolean getScrollsOnExpand()
2242:  {
2243:  return scrollsOnExpand;
2244:  }
2245: 
2246:  public void setScrollsOnExpand(boolean scroll)
2247:  {
2248:  clientScrollsOnExpandSet = true;
2249:  if (scrollsOnExpand == scroll)
2250:  return;
2251: 
2252:  boolean oldValue = scrollsOnExpand;
2253:  scrollsOnExpand = scroll;
2254:  firePropertyChange(SCROLLS_ON_EXPAND_PROPERTY, oldValue, scroll);
2255:  }
2256: 
2257:  public void setSelectionPath(TreePath path)
2258:  {
2259:  clearSelectionPathStates();
2260:  selectionModel.setSelectionPath(path);
2261:  }
2262: 
2263:  public void setSelectionPaths(TreePath[] paths)
2264:  {
2265:  clearSelectionPathStates();
2266:  selectionModel.setSelectionPaths(paths);
2267:  }
2268:  
2269:  /**
2270:  * This method, and all calls to it, should be removed once the
2271:  * DefaultTreeModel fires events properly. Maintenance of the nodeStates
2272:  * table should really be done in the TreeModelHandler. 
2273:  */
2274:  private void clearSelectionPathStates()
2275:  {
2276:  TreePath[] oldPaths = selectionModel.getSelectionPaths();
2277:  if (oldPaths != null)
2278:  for (int i = 0; i < oldPaths.length; i++)
2279:  nodeStates.remove(oldPaths[i]);
2280:  }
2281: 
2282:  public void setSelectionRow(int row)
2283:  {
2284:  TreePath path = getPathForRow(row);
2285: 
2286:  if (path != null)
2287:  setSelectionPath(path);
2288:  }
2289: 
2290:  public void setSelectionRows(int[] rows)
2291:  {
2292:  // Make sure we have an UI so getPathForRow() does not return null.
2293:  if (rows == null || getUI() == null)
2294:  return;
2295: 
2296:  TreePath[] paths = new TreePath[rows.length];
2297: 
2298:  for (int i = rows.length - 1; i >= 0; --i)
2299:  paths[i] = getPathForRow(rows[i]);
2300: 
2301:  setSelectionPaths(paths);
2302:  }
2303: 
2304:  public void setSelectionInterval(int index0, int index1)
2305:  {
2306:  TreePath[] paths = getPathBetweenRows(index0, index1);
2307: 
2308:  if (paths != null)
2309:  setSelectionPaths(paths);
2310:  }
2311: 
2312:  public void addSelectionPath(TreePath path)
2313:  {
2314:  selectionModel.addSelectionPath(path);
2315:  }
2316: 
2317:  public void addSelectionPaths(TreePath[] paths)
2318:  {
2319:  selectionModel.addSelectionPaths(paths);
2320:  }
2321: 
2322:  public void addSelectionRow(int row)
2323:  {
2324:  TreePath path = getPathForRow(row);
2325: 
2326:  if (path != null)
2327:  selectionModel.addSelectionPath(path);
2328:  }
2329: 
2330:  public void addSelectionRows(int[] rows)
2331:  {
2332:  // Make sure we have an UI so getPathForRow() does not return null.
2333:  if (rows == null || getUI() == null)
2334:  return;
2335: 
2336:  TreePath[] paths = new TreePath[rows.length];
2337: 
2338:  for (int i = rows.length - 1; i >= 0; --i)
2339:  paths[i] = getPathForRow(rows[i]);
2340: 
2341:  addSelectionPaths(paths);
2342:  }
2343:  
2344:  /**
2345:  * Select all rows between the two given indexes, inclusive. The method
2346:  * will not select the inner leaves and braches of the currently collapsed
2347:  * nodes in this interval.
2348:  * 
2349:  * @param index0 the starting row, inclusive
2350:  * @param index1 the ending row, inclusive
2351:  */
2352:  public void addSelectionInterval(int index0, int index1)
2353:  {
2354:  TreePath[] paths = getPathBetweenRows(index0, index1);
2355: 
2356:  if (paths != null)
2357:  addSelectionPaths(paths);
2358:  }
2359: 
2360:  public void removeSelectionPath(TreePath path)
2361:  {
2362:  clearSelectionPathStates();
2363:  selectionModel.removeSelectionPath(path);
2364:  }
2365: 
2366:  public void removeSelectionPaths(TreePath[] paths)
2367:  {
2368:  clearSelectionPathStates();
2369:  selectionModel.removeSelectionPaths(paths);
2370:  }
2371: 
2372:  public void removeSelectionRow(int row)
2373:  {
2374:  TreePath path = getPathForRow(row);
2375: 
2376:  if (path != null)
2377:  removeSelectionPath(path);
2378:  }
2379: 
2380:  public void removeSelectionRows(int[] rows)
2381:  {
2382:  if (rows == null || getUI() == null)
2383:  return;
2384: 
2385:  TreePath[] paths = new TreePath[rows.length];
2386: 
2387:  for (int i = rows.length - 1; i >= 0; --i)
2388:  paths[i] = getPathForRow(rows[i]);
2389: 
2390:  removeSelectionPaths(paths);
2391:  }
2392: 
2393:  public void removeSelectionInterval(int index0, int index1)
2394:  {
2395:  TreePath[] paths = getPathBetweenRows(index0, index1);
2396: 
2397:  if (paths != null)
2398:  removeSelectionPaths(paths);
2399:  }
2400: 
2401:  public void clearSelection()
2402:  {
2403:  selectionModel.clearSelection();
2404:  setLeadSelectionPath(null);
2405:  }
2406: 
2407:  public TreePath getLeadSelectionPath()
2408:  {
2409:  if (selectionModel == null)
2410:  return null;
2411:  else
2412:  return selectionModel.getLeadSelectionPath();
2413:  }
2414: 
2415:  /**
2416:  * @since 1.3
2417:  */
2418:  public void setLeadSelectionPath(TreePath path)
2419:  {
2420:  if (selectionModel != null)
2421:  {
2422:  TreePath oldValue = selectionModel.getLeadSelectionPath();
2423:  if (path == oldValue || path != null && path.equals(oldValue))
2424:  return;
2425:  
2426:  // Repaint the previous and current rows with the lead selection path.
2427:  if (path != null)
2428:  {
2429:  repaint(getPathBounds(path));
2430:  selectionModel.addSelectionPath(path);
2431:  }
2432:  
2433:  if (oldValue != null)
2434:  repaint(getPathBounds(oldValue));
2435:  
2436:  firePropertyChange(LEAD_SELECTION_PATH_PROPERTY, oldValue, path);
2437:  }
2438:  }
2439: 
2440:  /**
2441:  * @since 1.3
2442:  */
2443:  public TreePath getAnchorSelectionPath()
2444:  {
2445:  return anchorSelectionPath;
2446:  }
2447: 
2448:  /**
2449:  * @since 1.3
2450:  */
2451:  public void setAnchorSelectionPath(TreePath path)
2452:  {
2453:  if (anchorSelectionPath == path)
2454:  return;
2455: 
2456:  TreePath oldValue = anchorSelectionPath;
2457:  anchorSelectionPath = path;
2458:  firePropertyChange(ANCHOR_SELECTION_PATH_PROPERTY, oldValue, path);
2459:  }
2460: 
2461:  public int getLeadSelectionRow()
2462:  {
2463:  return selectionModel.getLeadSelectionRow();
2464:  }
2465: 
2466:  public int getMaxSelectionRow()
2467:  {
2468:  return selectionModel.getMaxSelectionRow();
2469:  }
2470: 
2471:  public int getMinSelectionRow()
2472:  {
2473:  return selectionModel.getMinSelectionRow();
2474:  }
2475: 
2476:  public int getSelectionCount()
2477:  {
2478:  return selectionModel.getSelectionCount();
2479:  }
2480: 
2481:  public TreePath getSelectionPath()
2482:  {
2483:  return selectionModel.getSelectionPath();
2484:  }
2485: 
2486:  public TreePath[] getSelectionPaths()
2487:  {
2488:  return selectionModel.getSelectionPaths();
2489:  }
2490: 
2491:  public int[] getSelectionRows()
2492:  {
2493:  return selectionModel.getSelectionRows();
2494:  }
2495: 
2496:  public boolean isPathSelected(TreePath path)
2497:  {
2498:  return selectionModel.isPathSelected(path);
2499:  }
2500: 
2501:  /**
2502:  * Returns <code>true</code> when the specified row is selected,
2503:  * <code>false</code> otherwise. This call is delegated to the
2504:  * {@link TreeSelectionModel#isRowSelected(int)} method.
2505:  *
2506:  * @param row the row to check
2507:  *
2508:  * @return <code>true</code> when the specified row is selected,
2509:  * <code>false</code> otherwise
2510:  */
2511:  public boolean isRowSelected(int row)
2512:  {
2513:  return selectionModel.isRowSelected(row);
2514:  }
2515: 
2516:  public boolean isSelectionEmpty()
2517:  {
2518:  return selectionModel.isSelectionEmpty();
2519:  }
2520: 
2521:  /**
2522:  * Return the value of the <code>dragEnabled</code> property.
2523:  * 
2524:  * @return the value
2525:  * 
2526:  * @since 1.4
2527:  */
2528:  public boolean getDragEnabled()
2529:  {
2530:  return dragEnabled;
2531:  }
2532: 
2533:  /**
2534:  * Set the <code>dragEnabled</code> property.
2535:  * 
2536:  * @param enabled new value
2537:  * 
2538:  * @since 1.4
2539:  */
2540:  public void setDragEnabled(boolean enabled)
2541:  {
2542:  dragEnabled = enabled;
2543:  }
2544: 
2545:  public int getRowCount()
2546:  {
2547:  TreeUI ui = getUI();
2548: 
2549:  if (ui != null)
2550:  return ui.getRowCount(this);
2551: 
2552:  return 0;
2553:  }
2554: 
2555:  public void collapsePath(TreePath path)
2556:  {
2557:  try
2558:  {
2559:  fireTreeWillCollapse(path);
2560:  }
2561:  catch (ExpandVetoException ev)
2562:  {
2563:  // We do nothing if attempt has been vetoed.
2564:  }
2565:  setExpandedState(path, false);
2566:  fireTreeCollapsed(path);
2567:  }
2568: 
2569:  public void collapseRow(int row)
2570:  {
2571:  if (row < 0 || row >= getRowCount())
2572:  return;
2573: 
2574:  TreePath path = getPathForRow(row);
2575: 
2576:  if (path != null)
2577:  collapsePath(path);
2578:  }
2579: 
2580:  public void expandPath(TreePath path)
2581:  {
2582:  // Don't expand if path is null
2583:  // or is already expanded.
2584:  if (path == null || isExpanded(path))
2585:  return;
2586: 
2587:  try
2588:  {
2589:  fireTreeWillExpand(path);
2590:  }
2591:  catch (ExpandVetoException ev)
2592:  {
2593:  // We do nothing if attempt has been vetoed.
2594:  }
2595: 
2596:  setExpandedState(path, true);
2597:  fireTreeExpanded(path);
2598:  }
2599: 
2600:  public void expandRow(int row)
2601:  {
2602:  if (row < 0 || row >= getRowCount())
2603:  return;
2604: 
2605:  TreePath path = getPathForRow(row);
2606: 
2607:  if (path != null)
2608:  expandPath(path);
2609:  }
2610: 
2611:  public boolean isCollapsed(TreePath path)
2612:  {
2613:  return !isExpanded(path);
2614:  }
2615: 
2616:  public boolean isCollapsed(int row)
2617:  {
2618:  if (row < 0 || row >= getRowCount())
2619:  return false;
2620: 
2621:  TreePath path = getPathForRow(row);
2622: 
2623:  if (path != null)
2624:  return isCollapsed(path);
2625: 
2626:  return false;
2627:  }
2628: 
2629:  public boolean isExpanded(TreePath path)
2630:  {
2631:  if (path == null)
2632:  return false;
2633: 
2634:  Object state = nodeStates.get(path);
2635: 
2636:  if ((state == null) || (state != EXPANDED))
2637:  return false;
2638: 
2639:  TreePath parent = path.getParentPath();
2640: 
2641:  if (parent != null)
2642:  return isExpanded(parent);
2643: 
2644:  return true;
2645:  }
2646: 
2647:  public boolean isExpanded(int row)
2648:  {
2649:  if (row < 0 || row >= getRowCount())
2650:  return false;
2651: 
2652:  TreePath path = getPathForRow(row);
2653: 
2654:  if (path != null)
2655:  return isExpanded(path);
2656: 
2657:  return false;
2658:  }
2659: 
2660:  /**
2661:  * @since 1.3
2662:  */
2663:  public boolean getExpandsSelectedPaths()
2664:  {
2665:  return expandsSelectedPaths;
2666:  }
2667: 
2668:  /**
2669:  * @since 1.3
2670:  */
2671:  public void setExpandsSelectedPaths(boolean flag)
2672:  {
2673:  if (expandsSelectedPaths == flag)
2674:  return;
2675: 
2676:  boolean oldValue = expandsSelectedPaths;
2677:  expandsSelectedPaths = flag;
2678:  firePropertyChange(EXPANDS_SELECTED_PATHS_PROPERTY, oldValue, flag);
2679:  }
2680: 
2681:  public Rectangle getPathBounds(TreePath path)
2682:  {
2683:  TreeUI ui = getUI();
2684: 
2685:  if (ui == null)
2686:  return null;
2687: 
2688:  return ui.getPathBounds(this, path);
2689:  }
2690: 
2691:  public Rectangle getRowBounds(int row)
2692:  {
2693:  TreePath path = getPathForRow(row);
2694: 
2695:  if (path != null)
2696:  return getPathBounds(path);
2697: 
2698:  return null;
2699:  }
2700: 
2701:  public boolean isEditing()
2702:  {
2703:  TreeUI ui = getUI();
2704: 
2705:  if (ui != null)
2706:  return ui.isEditing(this);
2707: 
2708:  return false;
2709:  }
2710: 
2711:  public boolean stopEditing()
2712:  {
2713:  TreeUI ui = getUI();
2714: 
2715:  if (isEditing())
2716:  if (ui != null)
2717:  return ui.stopEditing(this);
2718: 
2719:  return false;
2720:  }
2721: 
2722:  public void cancelEditing()
2723:  {
2724:  TreeUI ui = getUI();
2725:  
2726:  if (isEditing())
2727:  if (ui != null)
2728:  ui.cancelEditing(this);
2729:  }
2730: 
2731:  public void startEditingAtPath(TreePath path)
2732:  {
2733:  TreeUI ui = getUI();
2734: 
2735:  if (ui != null)
2736:  ui.startEditingAtPath(this, path);
2737:  }
2738: 
2739:  public TreePath getEditingPath()
2740:  {
2741:  TreeUI ui = getUI();
2742: 
2743:  if (ui != null)
2744:  return ui.getEditingPath(this);
2745: 
2746:  return null;
2747:  }
2748: 
2749:  public TreePath getPathForLocation(int x, int y)
2750:  {
2751:  TreePath path = getClosestPathForLocation(x, y);
2752: 
2753:  if (path != null)
2754:  {
2755:  Rectangle rect = getPathBounds(path);
2756: 
2757:  if ((rect != null) && rect.contains(x, y))
2758:  return path;
2759:  }
2760: 
2761:  return null;
2762:  }
2763: 
2764:  public int getRowForLocation(int x, int y)
2765:  {
2766:  TreePath path = getPathForLocation(x, y);
2767: 
2768:  if (path != null)
2769:  return getRowForPath(path);
2770: 
2771:  return -1;
2772:  }
2773: 
2774:  public TreePath getClosestPathForLocation(int x, int y)
2775:  {
2776:  TreeUI ui = getUI();
2777: 
2778:  if (ui != null)
2779:  return ui.getClosestPathForLocation(this, x, y);
2780: 
2781:  return null;
2782:  }
2783: 
2784:  public int getClosestRowForLocation(int x, int y)
2785:  {
2786:  TreePath path = getClosestPathForLocation(x, y);
2787: 
2788:  if (path != null)
2789:  return getRowForPath(path);
2790: 
2791:  return -1;
2792:  }
2793: 
2794:  public Object getLastSelectedPathComponent()
2795:  {
2796:  TreePath path = getSelectionPath();
2797: 
2798:  if (path != null)
2799:  return path.getLastPathComponent();
2800: 
2801:  return null;
2802:  }
2803: 
2804:  private void doExpandParents(TreePath path, boolean state)
2805:  {
2806:  TreePath parent = path.getParentPath(); 
2807: 
2808:  if (!isExpanded(parent) && parent != null)
2809:  doExpandParents(parent, false);
2810:  
2811:  nodeStates.put(path, state ? EXPANDED : COLLAPSED);
2812:  }
2813: 
2814:  protected void setExpandedState(TreePath path, boolean state)
2815:  {
2816:  if (path == null)
2817:  return;
2818: 
2819:  doExpandParents(path, state);
2820:  }
2821: 
2822:  protected void clearToggledPaths()
2823:  {
2824:  nodeStates.clear();
2825:  }
2826: 
2827:  protected Enumeration<TreePath> getDescendantToggledPaths(TreePath parent)
2828:  {
2829:  if (parent == null)
2830:  return null;
2831: 
2832:  Enumeration nodes = nodeStates.keys();
2833:  Vector result = new Vector();
2834: 
2835:  while (nodes.hasMoreElements())
2836:  {
2837:  TreePath path = (TreePath) nodes.nextElement();
2838: 
2839:  if (path.isDescendant(parent))
2840:  result.addElement(path);
2841:  }
2842: 
2843:  return result.elements();
2844:  }
2845: 
2846:  public boolean hasBeenExpanded(TreePath path)
2847:  {
2848:  if (path == null)
2849:  return false;
2850: 
2851:  return nodeStates.get(path) != null;
2852:  }
2853: 
2854:  public boolean isVisible(TreePath path)
2855:  {
2856:  if (path == null)
2857:  return false;
2858: 
2859:  TreePath parent = path.getParentPath();
2860: 
2861:  if (parent == null)
2862:  return true; // Is root node.
2863: 
2864:  return isExpanded(parent);
2865:  }
2866: 
2867:  public void makeVisible(TreePath path)
2868:  {
2869:  if (path == null)
2870:  return;
2871:  
2872:  expandPath(path.getParentPath());
2873:  }
2874: 
2875:  public boolean isPathEditable(TreePath path)
2876:  {
2877:  return isEditable();
2878:  }
2879: 
2880:  /**
2881:  * Creates and returns an instance of {@link TreeModelHandler}.
2882:  * 
2883:  * @return an instance of {@link TreeModelHandler}
2884:  */
2885:  protected TreeModelListener createTreeModelListener()
2886:  {
2887:  return new TreeModelHandler();
2888:  }
2889: 
2890:  /**
2891:  * Returns a sample TreeModel that can be used in a JTree. This can be used
2892:  * in Bean- or GUI-Builders to show something interesting.
2893:  * 
2894:  * @return a sample TreeModel that can be used in a JTree
2895:  */
2896:  protected static TreeModel getDefaultTreeModel()
2897:  {
2898:  DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root node");
2899:  DefaultMutableTreeNode child1 = new DefaultMutableTreeNode("Child node 1");
2900:  DefaultMutableTreeNode child11 =
2901:  new DefaultMutableTreeNode("Child node 1.1");
2902:  DefaultMutableTreeNode child12 =
2903:  new DefaultMutableTreeNode("Child node 1.2");
2904:  DefaultMutableTreeNode child13 =
2905:  new DefaultMutableTreeNode("Child node 1.3");
2906:  DefaultMutableTreeNode child2 = new DefaultMutableTreeNode("Child node 2");
2907:  DefaultMutableTreeNode child21 =
2908:  new DefaultMutableTreeNode("Child node 2.1");
2909:  DefaultMutableTreeNode child22 =
2910:  new DefaultMutableTreeNode("Child node 2.2");
2911:  DefaultMutableTreeNode child23 =
2912:  new DefaultMutableTreeNode("Child node 2.3");
2913:  DefaultMutableTreeNode child24 =
2914:  new DefaultMutableTreeNode("Child node 2.4");
2915: 
2916:  DefaultMutableTreeNode child3 = new DefaultMutableTreeNode("Child node 3");
2917:  root.add(child1);
2918:  root.add(child2);
2919:  root.add(child3);
2920:  child1.add(child11);
2921:  child1.add(child12);
2922:  child1.add(child13);
2923:  child2.add(child21);
2924:  child2.add(child22);
2925:  child2.add(child23);
2926:  child2.add(child24);
2927:  return new DefaultTreeModel(root);
2928:  }
2929: 
2930:  /**
2931:  * Converts the specified value to a String. This is used by the renderers
2932:  * of this JTree and its nodes.
2933:  * 
2934:  * This implementation simply returns <code>value.toString()</code> and
2935:  * ignores all other parameters. Subclass this method to control the
2936:  * conversion.
2937:  * 
2938:  * @param value the value that is converted to a String
2939:  * @param selected indicates if that value is selected or not
2940:  * @param expanded indicates if that value is expanded or not
2941:  * @param leaf indicates if that value is a leaf node or not
2942:  * @param row the row of the node
2943:  * @param hasFocus indicates if that node has focus or not
2944:  */
2945:  public String convertValueToText(Object value, boolean selected,
2946:  boolean expanded, boolean leaf, int row, boolean hasFocus)
2947:  {
2948:  return value.toString();
2949:  }
2950: 
2951:  /**
2952:  * A String representation of this JTree. This is intended to be used for
2953:  * debugging. The returned string may be empty but may not be
2954:  * <code>null</code>.
2955:  * 
2956:  * @return a String representation of this JTree
2957:  */
2958:  protected String paramString()
2959:  {
2960:  // TODO: this is completely legal, but it would possibly be nice
2961:  // to return some more content, like the tree structure, some properties
2962:  // etc ...
2963:  return "";
2964:  }
2965: 
2966:  /**
2967:  * Returns all TreePath objects which are a descendants of the given path
2968:  * and are exapanded at the moment of the execution of this method. If the
2969:  * state of any node is beeing toggled while this method is executing this
2970:  * change may be left unaccounted.
2971:  * 
2972:  * @param path The parent of this request
2973:  *
2974:  * @return An Enumeration containing TreePath objects
2975:  */
2976:  public Enumeration<TreePath> getExpandedDescendants(TreePath path)
2977:  {
2978:  Enumeration paths = nodeStates.keys();
2979:  Vector relevantPaths = new Vector();
2980:  while (paths.hasMoreElements())
2981:  {
2982:  TreePath nextPath = (TreePath) paths.nextElement();
2983:  if (nodeStates.get(nextPath) == EXPANDED
2984:  && path.isDescendant(nextPath))
2985:  {
2986:  relevantPaths.add(nextPath);
2987:  }
2988:  }
2989:  return relevantPaths.elements();
2990:  }
2991: 
2992:  /**
2993:  * Returns the next table element (beginning from the row
2994:  * <code>startingRow</code> that starts with <code>prefix</code>.
2995:  * Searching is done in the direction specified by <code>bias</code>.
2996:  * 
2997:  * @param prefix the prefix to search for in the cell values
2998:  * @param startingRow the index of the row where to start searching from
2999:  * @param bias the search direction, either {@link Position.Bias#Forward} or
3000:  * {@link Position.Bias#Backward}
3001:  * 
3002:  * @return the path to the found element or -1 if no such element has been
3003:  * found
3004:  * 
3005:  * @throws IllegalArgumentException if prefix is <code>null</code> or
3006:  * startingRow is not valid
3007:  * 
3008:  * @since 1.4
3009:  */
3010:  public TreePath getNextMatch(String prefix, int startingRow,
3011:  Position.Bias bias)
3012:  {
3013:  if (prefix == null)
3014:  throw new IllegalArgumentException("The argument 'prefix' must not be"
3015:  + " null.");
3016:  if (startingRow < 0)
3017:  throw new IllegalArgumentException("The argument 'startingRow' must not"
3018:  + " be less than zero.");
3019: 
3020:  int size = getRowCount();
3021:  if (startingRow > size)
3022:  throw new IllegalArgumentException("The argument 'startingRow' must not"
3023:  + " be greater than the number of"
3024:  + " elements in the TreeModel.");
3025: 
3026:  TreePath foundPath = null;
3027:  if (bias == Position.Bias.Forward)
3028:  {
3029:  for (int i = startingRow; i < size; i++)
3030:  {
3031:  TreePath path = getPathForRow(i);
3032:  Object o = path.getLastPathComponent();
3033:  // FIXME: in the following call to convertValueToText the
3034:  // last argument (hasFocus) should be done right.
3035:  String item = convertValueToText(o, isRowSelected(i),
3036:  isExpanded(i), treeModel.isLeaf(o),
3037:  i, false);
3038:  if (item.startsWith(prefix))
3039:  {
3040:  foundPath = path;
3041:  break;
3042:  }
3043:  }
3044:  }
3045:  else
3046:  {
3047:  for (int i = startingRow; i >= 0; i--)
3048:  {
3049:  TreePath path = getPathForRow(i);
3050:  Object o = path.getLastPathComponent();
3051:  // FIXME: in the following call to convertValueToText the
3052:  // last argument (hasFocus) should be done right.
3053:  String item = convertValueToText(o, isRowSelected(i),
3054:  isExpanded(i), treeModel.isLeaf(o), i, false);
3055:  if (item.startsWith(prefix))
3056:  {
3057:  foundPath = path;
3058:  break;
3059:  }
3060:  }
3061:  }
3062:  return foundPath;
3063:  }
3064: 
3065:  /**
3066:  * Removes any paths in the current set of selected paths that are
3067:  * descendants of <code>path</code>. If <code>includePath</code> is set
3068:  * to <code>true</code> and <code>path</code> itself is selected, then
3069:  * it will be removed too.
3070:  * 
3071:  * @param path the path from which selected descendants are to be removed
3072:  * @param includeSelected if <code>true</code> then <code>path</code> itself
3073:  * will also be remove if it's selected
3074:  * 
3075:  * @return <code>true</code> if something has been removed,
3076:  * <code>false</code> otherwise
3077:  * 
3078:  * @since 1.3
3079:  */
3080:  protected boolean removeDescendantSelectedPaths(TreePath path,
3081:  boolean includeSelected)
3082:  {
3083:  boolean removedSomething = false;
3084:  TreePath[] selected = getSelectionPaths();
3085:  for (int index = 0; index < selected.length; index++)
3086:  {
3087:  if ((selected[index] == path && includeSelected)
3088:  || (selected[index].isDescendant(path)))
3089:  {
3090:  removeSelectionPath(selected[index]);
3091:  removedSomething = true;
3092:  }
3093:  }
3094:  return removedSomething;
3095:  }
3096:  
3097:  /**
3098:  * Removes any descendants of the TreePaths in toRemove that have been 
3099:  * expanded.
3100:  * 
3101:  * @param toRemove - Enumeration of TreePaths that need to be removed from
3102:  * cache of toggled tree paths.
3103:  */
3104:  protected void removeDescendantToggledPaths(Enumeration<TreePath> toRemove)
3105:  {
3106:  while (toRemove.hasMoreElements())
3107:  {
3108:  TreePath current = (TreePath) toRemove.nextElement();
3109:  Enumeration descendants = getDescendantToggledPaths(current);
3110:  
3111:  while (descendants.hasMoreElements())
3112:  {
3113:  TreePath currentDes = (TreePath) descendants.nextElement();
3114:  if (isExpanded(currentDes))
3115:  nodeStates.remove(currentDes);
3116:  }
3117:  }
3118:  }
3119: 
3120:  /**
3121:  * <p>
3122:  * Sent when the tree has changed enough that we need to resize the bounds,
3123:  * but not enough that we need to remove the expanded node set (e.g nodes were
3124:  * expanded or collapsed, or nodes were inserted into the tree). You should
3125:  * never have to invoke this, the UI will invoke this as it needs to.
3126:  * </p>
3127:  * <p>
3128:  * If the tree uses {@link DefaultTreeModel}, you must call
3129:  * {@link DefaultTreeModel#reload(TreeNode)} or
3130:  * {@link DefaultTreeModel#reload()} after adding or removing nodes. Following
3131:  * the official Java 1.5 API standard, just calling treeDidChange, repaint()
3132:  * or revalidate() does <i>not</i> update the tree appearance properly.
3133:  * 
3134:  * @see DefaultTreeModel#reload()
3135:  */
3136:  public void treeDidChange()
3137:  {
3138:  repaint();
3139:  }
3140: 
3141:  /**
3142:  * Helper method for
3143:  * {@link LookAndFeel#installProperty(JComponent, String, Object)}.
3144:  * 
3145:  * @param propertyName the name of the property
3146:  * @param value the value of the property
3147:  *
3148:  * @throws IllegalArgumentException if the specified property cannot be set
3149:  * by this method
3150:  * @throws ClassCastException if the property value does not match the
3151:  * property type
3152:  * @throws NullPointerException if <code>c</code> or
3153:  * <code>propertyValue</code> is <code>null</code>
3154:  */
3155:  void setUIProperty(String propertyName, Object value)
3156:  {
3157:  if (propertyName.equals("rowHeight"))
3158:  {
3159:  if (! clientRowHeightSet)
3160:  {
3161:  setRowHeight(((Integer) value).intValue());
3162:  clientRowHeightSet = false;
3163:  }
3164:  }
3165:  else if (propertyName.equals("scrollsOnExpand"))
3166:  {
3167:  if (! clientScrollsOnExpandSet)
3168:  {
3169:  setScrollsOnExpand(((Boolean) value).booleanValue());
3170:  clientScrollsOnExpandSet = false;
3171:  }
3172:  }
3173:  else if (propertyName.equals("showsRootHandles"))
3174:  {
3175:  if (! clientShowsRootHandlesSet)
3176:  {
3177:  setShowsRootHandles(((Boolean) value).booleanValue());
3178:  clientShowsRootHandlesSet = false;
3179:  }
3180:  }
3181:  else
3182:  {
3183:  super.setUIProperty(propertyName, value);
3184:  }
3185:  }
3186: }
Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)

AltStyle によって変換されたページ (->オリジナル) /