Source for javax.swing.tree.DefaultTreeCellEditor

   1: /* DefaultTreeCellEditor.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: 
  39: package javax.swing.tree;
  40: 
  41: import java.awt.Color;
  42: import java.awt.Component;
  43: import java.awt.Container;
  44: import java.awt.Dimension;
  45: import java.awt.Font;
  46: import java.awt.FontMetrics;
  47: import java.awt.Graphics;
  48: import java.awt.Rectangle;
  49: import java.awt.event.ActionEvent;
  50: import java.awt.event.ActionListener;
  51: import java.awt.event.MouseEvent;
  52: import java.io.IOException;
  53: import java.io.ObjectInputStream;
  54: import java.io.ObjectOutputStream;
  55: import java.util.EventObject;
  56: 
  57: import javax.swing.DefaultCellEditor;
  58: import javax.swing.Icon;
  59: import javax.swing.JTextField;
  60: import javax.swing.JTree;
  61: import javax.swing.SwingUtilities;
  62: import javax.swing.UIManager;
  63: import javax.swing.border.Border;
  64: import javax.swing.event.CellEditorListener;
  65: import javax.swing.event.ChangeEvent;
  66: import javax.swing.event.EventListenerList;
  67: import javax.swing.event.TreeSelectionEvent;
  68: import javax.swing.event.TreeSelectionListener;
  69: 
  70: /**
  71:  * Participates in the tree cell editing.
  72:  * 
  73:  * @author Andrew Selkirk
  74:  * @author Audrius Meskauskas
  75:  */
  76: public class DefaultTreeCellEditor
  77:   implements ActionListener, TreeCellEditor, TreeSelectionListener
  78: {
  79:   /**
  80:    * The number of the fast mouse clicks, required to start the editing 
  81:    * session.
  82:    */
  83:   static int CLICK_COUNT_TO_START = 3;
  84:   
  85:   /**
  86:    * This container that appears on the tree during editing session.
  87:    * It contains the editing component displays various other editor - 
  88:    * specific parts like editing icon. 
  89:    */
  90:   public class EditorContainer extends Container
  91:   {
  92:    /**
  93:     * Use v 1.5 serial version UID for interoperability.
  94:     */
  95:     static final long serialVersionUID = 6470339600449699810L;
  96:     
  97:     /**
  98:      * Creates an <code>EditorContainer</code> object.
  99:      */
 100:     public EditorContainer()
 101:     {
 102:       // Do nothing here.
 103:     }
 104: 
 105:     /**
 106:      * This method only exists for API compatibility and is useless as it does
 107:      * nothing. It got probably introduced by accident.
 108:      */
 109:     public void EditorContainer()
 110:     {
 111:       // Do nothing here.
 112:     }
 113:    
 114:     public void setBounds(Rectangle bounds)
 115:     {
 116:       super.setBounds(bounds);
 117:       doLayout();
 118:     }
 119: 
 120:     /**
 121:      * Overrides Container.paint to paint the node's icon and use the selection
 122:      * color for the background.
 123:      * 
 124:      * @param g -
 125:      *          the specified Graphics window
 126:      */
 127:     public void paint(Graphics g)
 128:     {
 129:       if (editingIcon != null)
 130:         {
 131:           // From the previous version, the left margin is taken as half
 132:           // of the icon width.
 133:           editingIcon.paintIcon(this, g, 0, 0);
 134:         }
 135:       super.paint(g);
 136:     }
 137: 
 138:     /**
 139:      * Lays out this Container, moving the editor component to the left
 140:      * (leaving place for the icon).
 141:      */
 142:     public void doLayout()
 143:     {
 144:       // The offset of the editing component.
 145:       int eOffset;
 146: 
 147:       // Move the component to the left, leaving room for the editing icon:
 148:       if (editingIcon != null)
 149:         eOffset = editingIcon.getIconWidth();
 150:       else
 151:         eOffset = 0;
 152: 
 153:       Rectangle bounds = getBounds();
 154:       Component c = getComponent(0);
 155:       c.setLocation(eOffset, 0);
 156: 
 157:       // Span the editing component near over all window width.
 158:       c.setSize(bounds.width - eOffset, bounds.height);
 159:       /*
 160:        * @specnote the Sun sets some more narrow editing component width (it is
 161:        * not documented how does it is calculated). However as our text field is
 162:        * still not able to auto - scroll horizontally, replicating such strategy
 163:        * would prevent adding extra characters to the text being edited.
 164:        */
 165:     }
 166:   }
 167: 
 168:   /**
 169:    * The default text field, used in the editing sessions.
 170:    */
 171:   public class DefaultTextField extends JTextField
 172:   {
 173:    /**
 174:     * Use v 1.5 serial version UID for interoperability.
 175:     */
 176:     static final long serialVersionUID = -6629304544265300143L; 
 177:     
 178:     /**
 179:      * The border of the text field.
 180:      */
 181:     protected Border border;
 182: 
 183:     /**
 184:      * Creates a <code>DefaultTextField</code> object.
 185:      *
 186:      * @param aBorder the border to use
 187:      */
 188:     public DefaultTextField(Border aBorder)
 189:     {
 190:       border = aBorder;
 191:     }
 192: 
 193:     /**
 194:      * Gets the font of this component.
 195:      * @return this component's font; if a font has not been set for 
 196:      * this component, the font of its parent is returned (if the parent
 197:      * is not null, otherwise null is returned). 
 198:      */
 199:     public Font getFont()
 200:     {
 201:       Font font = super.getFont();
 202:       if (font == null)
 203:         {
 204:           Component parent = getParent();
 205:           if (parent != null)
 206:             return parent.getFont();
 207:           return null;
 208:         }
 209:       return font;
 210:     }
 211: 
 212:     /**
 213:      * Returns the border of the text field.
 214:      *
 215:      * @return the border
 216:      */
 217:     public Border getBorder()
 218:     {
 219:       return border;
 220:     }
 221: 
 222:     /**
 223:      * Overrides JTextField.getPreferredSize to return the preferred size 
 224:      * based on current font, if set, or else use renderer's font.
 225:      * 
 226:      * @return the Dimension of this textfield.
 227:      */
 228:     public Dimension getPreferredSize()
 229:     {
 230:       String s = getText();
 231: 
 232:       Font f = getFont();
 233: 
 234:       if (f != null)
 235:         {
 236:           FontMetrics fm = getToolkit().getFontMetrics(f);
 237: 
 238:           return new Dimension(SwingUtilities.computeStringWidth(fm, s),
 239:                                fm.getHeight());
 240:         }
 241:       return renderer.getPreferredSize();
 242:     }
 243:   }
 244:   
 245:   /**
 246:    * Listens for the events from the realEditor.
 247:    */
 248:   class RealEditorListener implements CellEditorListener
 249:   {
 250:     /**
 251:      * The method is called when the editing has been cancelled.
 252:      * @param event unused
 253:      */
 254:     public void editingCanceled(ChangeEvent event)
 255:     {
 256:       cancelCellEditing();
 257:     }
 258: 
 259:     /**
 260:      * The method is called after completing the editing session.
 261:      * 
 262:      * @param event unused
 263:      */
 264:     public void editingStopped(ChangeEvent event)
 265:     {
 266:       stopCellEditing();
 267:     }
 268:   }
 269: 
 270:   private EventListenerList listenerList = new EventListenerList();
 271:   
 272:   /**
 273:    * Editor handling the editing.
 274:    */
 275:   protected TreeCellEditor realEditor;
 276: 
 277:   /**
 278:    * Renderer, used to get border and offsets from.
 279:    */
 280:   protected DefaultTreeCellRenderer renderer;
 281: 
 282:   /**
 283:    * Editing container, will contain the editorComponent.
 284:    */
 285:   protected Container editingContainer;
 286: 
 287:   /**
 288:    * Component used in editing, obtained from the editingContainer.
 289:    */
 290:   protected transient Component editingComponent;
 291: 
 292:   /**
 293:    * As of Java 2 platform v1.4 this field should no longer be used. 
 294:    * If you wish to provide similar behavior you should directly 
 295:    * override isCellEditable.
 296:    */
 297:   protected boolean canEdit;
 298: 
 299:   /**
 300:    * Used in editing. Indicates x position to place editingComponent.
 301:    */
 302:   protected transient int offset;
 303: 
 304:   /**
 305:    * JTree instance listening too.
 306:    */
 307:   protected transient JTree tree;
 308: 
 309:   /**
 310:    * Last path that was selected.
 311:    */
 312:   protected transient TreePath lastPath;
 313: 
 314:   /**
 315:    * Used before starting the editing session.
 316:    */
 317:   protected transient javax.swing.Timer timer;
 318: 
 319:   /**
 320:    * Row that was last passed into getTreeCellEditorComponent.
 321:    */
 322:   protected transient int lastRow;
 323: 
 324:   /**
 325:    * True if the border selection color should be drawn.
 326:    */
 327:   protected Color borderSelectionColor;
 328: 
 329:   /**
 330:    * Icon to use when editing.
 331:    */
 332:   protected transient Icon editingIcon;
 333: 
 334:   /**
 335:    * Font to paint with, null indicates font of renderer is to be used.
 336:    */
 337:   protected Font font;
 338:   
 339:   /**
 340:    * Helper field used to save the last path seen while the timer was
 341:    * running.
 342:    */
 343:     private TreePath tPath;
 344:     
 345:   /**
 346:    * Constructs a DefaultTreeCellEditor object for a JTree using the 
 347:    * specified renderer and a default editor. (Use this constructor 
 348:    * for normal editing.)
 349:    * 
 350:    * @param tree - a JTree object
 351:    * @param renderer - a DefaultTreeCellRenderer object
 352:    */
 353:   public DefaultTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer)
 354:   {
 355:     this(tree, renderer, null);
 356:   }
 357: 
 358:   /**
 359:    * Constructs a DefaultTreeCellEditor  object for a JTree using the specified 
 360:    * renderer and the specified editor. (Use this constructor 
 361:    * for specialized editing.)
 362:    * 
 363:    * @param tree - a JTree object
 364:    * @param renderer - a DefaultTreeCellRenderer object
 365:    * @param editor - a TreeCellEditor object
 366:    */
 367:   public DefaultTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer,
 368:                                TreeCellEditor editor)
 369:   {
 370:     setTree(tree);
 371:     this.renderer = renderer;
 372:     
 373:     if (editor == null)
 374:       editor = createTreeCellEditor();
 375:     else
 376:       editor.addCellEditorListener(new RealEditorListener());
 377:     
 378:     realEditor = editor;
 379:     
 380:     lastPath = tree.getLeadSelectionPath();
 381:     tree.addTreeSelectionListener(this);
 382:     editingContainer = createContainer();
 383:     setFont(UIManager.getFont("Tree.font"));
 384:     setBorderSelectionColor(UIManager.getColor("Tree.selectionBorderColor"));
 385:     editingIcon = renderer.getIcon();
 386:   }
 387: 
 388:   /**
 389:    * Configures the editing component whenever it is null.
 390:    * 
 391:    * @param tree the tree to configure to component for.
 392:    * @param renderer the renderer used to set up the nodes
 393:    * @param editor the editor used 
 394:    */
 395:   private void configureEditingComponent(JTree tree,
 396:                                          DefaultTreeCellRenderer renderer,
 397:                                          TreeCellEditor editor)
 398:   {    
 399:     if (tree != null && lastPath != null)
 400:       {
 401:         Object val = lastPath.getLastPathComponent();
 402:         boolean isLeaf = tree.getModel().isLeaf(val);
 403:         boolean expanded = tree.isExpanded(lastPath);
 404:         determineOffset(tree, val, true, expanded, isLeaf, lastRow);
 405: 
 406:         // set up icon
 407:         if (isLeaf)
 408:           renderer.setIcon(renderer.getLeafIcon());
 409:         else if (expanded)
 410:           renderer.setIcon(renderer.getOpenIcon());
 411:         else
 412:           renderer.setIcon(renderer.getClosedIcon());
 413:         editingIcon = renderer.getIcon();
 414:         
 415:         editingComponent = getTreeCellEditorComponent(tree, val, true,
 416:                                                       expanded, isLeaf, lastRow);
 417:       }
 418:   }
 419:   
 420:   /**
 421:    * writeObject
 422:    * 
 423:    * @param value0
 424:    *          TODO
 425:    * @exception IOException
 426:    *              TODO
 427:    */
 428:   private void writeObject(ObjectOutputStream value0) throws IOException
 429:   {
 430:     // TODO
 431:   }
 432: 
 433:   /**
 434:    * readObject
 435:    * @param value0 TODO
 436:    * @exception IOException TODO
 437:    * @exception ClassNotFoundException TODO
 438:    */
 439:   private void readObject(ObjectInputStream value0)
 440:     throws IOException, ClassNotFoundException
 441:   {
 442:     // TODO
 443:   }
 444: 
 445:   /**
 446:    * Sets the color to use for the border.
 447:    * @param newColor - the new border color
 448:    */
 449:   public void setBorderSelectionColor(Color newColor)
 450:   {
 451:     this.borderSelectionColor = newColor;
 452:   }
 453: 
 454:   /**
 455:    * Returns the color the border is drawn.
 456:    * @return Color
 457:    */
 458:   public Color getBorderSelectionColor()
 459:   {
 460:     return borderSelectionColor;
 461:   }
 462: 
 463:   /**
 464:    * Sets the font to edit with. null indicates the renderers 
 465:    * font should be used. This will NOT override any font you have 
 466:    * set in the editor the receiver was instantied with. If null for 
 467:    * an editor was passed in, a default editor will be created that 
 468:    * will pick up this font.
 469:    * 
 470:    * @param font - the editing Font
 471:    */
 472:   public void setFont(Font font)
 473:   {
 474:     if (font != null)
 475:       this.font = font;
 476:     else
 477:       this.font = renderer.getFont();
 478:   }
 479: 
 480:   /**
 481:    * Gets the font used for editing.
 482:    * 
 483:    * @return the editing font
 484:    */
 485:   public Font getFont()
 486:   {
 487:     return font;
 488:   }
 489: 
 490:   /**
 491:    * Configures the editor. Passed onto the realEditor.
 492:    * Sets an initial value for the editor. This will cause 
 493:    * the editor to stopEditing and lose any partially edited value 
 494:    * if the editor is editing when this method is called. 
 495:    * Returns the component that should be added to the client's Component 
 496:    * hierarchy. Once installed in the client's hierarchy this component will 
 497:    * then be able to draw and receive user input. 
 498:    * 
 499:    * @param tree - the JTree that is asking the editor to edit; this parameter can be null
 500:    * @param value - the value of the cell to be edited
 501:    * @param isSelected - true is the cell is to be rendered with selection highlighting
 502:    * @param expanded - true if the node is expanded
 503:    * @param leaf - true if the node is a leaf node
 504:    * @param row - the row index of the node being edited
 505:    * 
 506:    * @return the component for editing
 507:    */
 508:   public Component getTreeCellEditorComponent(JTree tree, Object value,
 509:                                               boolean isSelected, boolean expanded,
 510:                                               boolean leaf, int row)
 511:   {
 512:     if (realEditor == null)
 513:       realEditor = createTreeCellEditor();
 514: 
 515:     return realEditor.getTreeCellEditorComponent(tree, value, isSelected,
 516:                                                         expanded, leaf, row);
 517:   }
 518: 
 519:   /**
 520:    * Returns the value currently being edited (requests it from the
 521:    * {@link realEditor}.
 522:    * 
 523:    * @return the value currently being edited
 524:    */
 525:   public Object getCellEditorValue()
 526:   {
 527:     return realEditor.getCellEditorValue();
 528:   }
 529:   
 530:   /**
 531:    * If the realEditor returns true to this message, prepareForEditing  
 532:    * is messaged and true is returned.
 533:    * 
 534:    * @param event - the event the editor should use to consider whether to 
 535:    * begin editing or not
 536:    * @return true if editing can be started
 537:    */
 538:   public boolean isCellEditable(EventObject event)
 539:   { 
 540:     if (editingComponent == null)
 541:         configureEditingComponent(tree, renderer, realEditor);
 542:     
 543:     if (editingComponent != null && realEditor.isCellEditable(event))
 544:       {
 545:         prepareForEditing();
 546:         return true;
 547:       }
 548:     return false;
 549:   }
 550: 
 551:   /**
 552:    * Messages the realEditor for the return value.
 553:    * 
 554:    * @param event -
 555:    *          the event the editor should use to start editing
 556:    * @return true if the editor would like the editing cell to be selected;
 557:    *         otherwise returns false
 558:    */
 559:   public boolean shouldSelectCell(EventObject event)
 560:   {
 561:     return true;
 562:   }
 563: 
 564:   /**
 565:    * If the realEditor will allow editing to stop, the realEditor
 566:    * is removed and true is returned, otherwise false is returned.
 567:    * @return true if editing was stopped; false otherwise
 568:    */
 569:   public boolean stopCellEditing()
 570:   {
 571:     if (editingComponent != null)
 572:       {
 573:         stopEditingTimer();
 574:         tree.stopEditing();
 575:         editingComponent = null;
 576:         return true;
 577:       }
 578:     return false;
 579:   }
 580: 
 581:   /**
 582:    * Messages cancelCellEditing to the realEditor and removes it
 583:    * from this instance.
 584:    */
 585:   public void cancelCellEditing()
 586:   {
 587:     if (editingComponent != null)
 588:       {
 589:         tree.cancelEditing();
 590:         editingComponent = null;
 591:       }
 592:     stopEditingTimer();
 593:   }
 594:   
 595:   /**
 596:    * Stop the editing timer, if it is installed and running.
 597:    */
 598:   private void stopEditingTimer()
 599:   {
 600:     if (timer != null && timer.isRunning())
 601:       timer.stop();
 602:   }
 603: 
 604:   /**
 605:    * Adds a <code>CellEditorListener</code> object to this editor.
 606:    * 
 607:    * @param listener
 608:    *          the listener to add
 609:    */
 610:   public void addCellEditorListener(CellEditorListener listener)
 611:   {
 612:     realEditor.addCellEditorListener(listener);
 613:   }
 614: 
 615:   /**
 616:    * Removes a <code>CellEditorListener</code> object.
 617:    *
 618:    * @param listener the listener to remove
 619:    */
 620:   public void removeCellEditorListener(CellEditorListener listener)
 621:   {
 622:     realEditor.removeCellEditorListener(listener);
 623:   }
 624: 
 625:   /**
 626:    * Returns all added <code>CellEditorListener</code> objects to this editor.
 627:    *
 628:    * @return an array of listeners
 629:    *
 630:    * @since 1.4
 631:    */
 632:   public CellEditorListener[] getCellEditorListeners()
 633:   {
 634:     return (CellEditorListener[]) listenerList.getListeners(CellEditorListener.class);
 635:   }
 636: 
 637:   /**
 638:    * Resets lastPath.
 639:    * 
 640:    * @param e - the event that characterizes the change.
 641:    */
 642:   public void valueChanged(TreeSelectionEvent e)
 643:   {
 644:     tPath = lastPath;
 645:     lastPath = e.getNewLeadSelectionPath();
 646:     lastRow = tree.getRowForPath(lastPath);
 647:     stopCellEditing();
 648:   }
 649:   
 650:   /**
 651:    * Messaged when the timer fires.
 652:    * 
 653:    * @param e the event that characterizes the action.
 654:    */
 655:   public void actionPerformed(ActionEvent e)
 656:   {
 657:   }
 658: 
 659:   /**
 660:    * Sets the tree currently editing for. This is needed to add a selection
 661:    * listener.
 662:    * 
 663:    * @param newTree -
 664:    *          the new tree to be edited
 665:    */
 666:   protected void setTree(JTree newTree)
 667:   {
 668:     tree = newTree;
 669:   }
 670: 
 671:   /**
 672:    * Returns true if event is a MouseEvent and the click count is 1.
 673:    * 
 674:    * @param event - the event being studied
 675:    * @return true if editing should start
 676:    */
 677:   protected boolean shouldStartEditingTimer(EventObject event)
 678:   {
 679:     if ((event instanceof MouseEvent) && 
 680:         ((MouseEvent) event).getClickCount() == 1)
 681:       return true;
 682:     return false;
 683:   }
 684: 
 685:   /**
 686:    * Starts the editing timer (if one installed). 
 687:    */
 688:   protected void startEditingTimer()
 689:   {
 690:     if (timer != null)
 691:       timer.start();
 692:   }
 693: 
 694:   /**
 695:    * Returns true if event is null, or it is a MouseEvent with 
 696:    * a click count > 2 and inHitRegion returns true.
 697:    * 
 698:    * @param event - the event being studied
 699:    * @return true if event is null, or it is a MouseEvent with 
 700:    * a click count > 2 and inHitRegion returns true 
 701:    */
 702:   protected boolean canEditImmediately(EventObject event)
 703:   {
 704:     if (event == null || !(event instanceof MouseEvent) || (((MouseEvent) event).
 705:         getClickCount() > 2 && inHitRegion(((MouseEvent) event).getX(), 
 706:                                          ((MouseEvent) event).getY())))
 707:       return true;
 708:     return false;
 709:   }
 710: 
 711:   /**
 712:    * Returns true if the passed in location is a valid mouse location 
 713:    * to start editing from. This is implemented to return false if x is
 714:    * less than or equal to the width of the icon and icon 
 715:    * gap displayed by the renderer. In other words this returns true if 
 716:    * the user clicks over the text part displayed by the renderer, and 
 717:    * false otherwise.
 718:    * 
 719:    * @param x - the x-coordinate of the point
 720:    * @param y - the y-coordinate of the point
 721:    * 
 722:    * @return true if the passed in location is a valid mouse location
 723:    */
 724:   protected boolean inHitRegion(int x, int y)
 725:   {
 726:     Rectangle bounds = tree.getPathBounds(lastPath);
 727:     
 728:     return bounds.contains(x, y);
 729:   }
 730: 
 731:   /**
 732:    * determineOffset
 733:    * @param tree -
 734:    * @param value - 
 735:    * @param isSelected - 
 736:    * @param expanded - 
 737:    * @param leaf - 
 738:    * @param row - 
 739:    */
 740:   protected void determineOffset(JTree tree, Object value, boolean isSelected,
 741:                                  boolean expanded, boolean leaf, int row)
 742:   {
 743:     renderer.getTreeCellRendererComponent(tree, value, isSelected, expanded, 
 744:                                           leaf, row, true);
 745:     Icon c = renderer.getIcon();
 746:     if (c != null)
 747:         offset = renderer.getIconTextGap() + c.getIconWidth();
 748:     else
 749:       offset = 0;
 750:   }
 751: 
 752:   /**
 753:    * Invoked just before editing is to start. Will add the 
 754:    * editingComponent to the editingContainer.
 755:    */
 756:   protected void prepareForEditing()
 757:   {
 758:     editingContainer.removeAll();
 759:     editingContainer.add(editingComponent);
 760:   }
 761: 
 762:   /**
 763:    * Creates the container to manage placement of editingComponent.
 764:    * 
 765:    * @return the container to manage the placement of the editingComponent.
 766:    */
 767:   protected Container createContainer()
 768:   {
 769:     return new DefaultTreeCellEditor.EditorContainer();
 770:   }
 771: 
 772:   /**
 773:    * This is invoked if a TreeCellEditor is not supplied in the constructor. 
 774:    * It returns a TextField editor.
 775:    * 
 776:    * @return a new TextField editor
 777:    */
 778:   protected TreeCellEditor createTreeCellEditor()
 779:   {
 780:     DefaultCellEditor editor = new DefaultCellEditor(new DefaultTreeCellEditor.DefaultTextField(
 781:                                   UIManager.getBorder("Tree.selectionBorder")));
 782:     editor.addCellEditorListener(new RealEditorListener());
 783:     editor.setClickCountToStart(CLICK_COUNT_TO_START);
 784:     realEditor = editor;
 785:     return editor;
 786:   }
 787: }