Source for javax.swing.JComponent

   1: /* JComponent.java -- Every component in swing inherits from this class.
   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;
  40: 
  41: import java.applet.Applet;
  42: import java.awt.AWTEvent;
  43: import java.awt.Color;
  44: import java.awt.Component;
  45: import java.awt.Container;
  46: import java.awt.Dimension;
  47: import java.awt.EventQueue;
  48: import java.awt.FlowLayout;
  49: import java.awt.FocusTraversalPolicy;
  50: import java.awt.Font;
  51: import java.awt.Graphics;
  52: import java.awt.Graphics2D;
  53: import java.awt.Image;
  54: import java.awt.Insets;
  55: import java.awt.Point;
  56: import java.awt.Rectangle;
  57: import java.awt.Shape;
  58: import java.awt.Window;
  59: import java.awt.dnd.DropTarget;
  60: import java.awt.event.ActionEvent;
  61: import java.awt.event.ActionListener;
  62: import java.awt.event.ContainerEvent;
  63: import java.awt.event.ContainerListener;
  64: import java.awt.event.FocusEvent;
  65: import java.awt.event.FocusListener;
  66: import java.awt.event.KeyEvent;
  67: import java.awt.event.MouseEvent;
  68: import java.awt.geom.Rectangle2D;
  69: import java.awt.peer.LightweightPeer;
  70: import java.beans.PropertyChangeEvent;
  71: import java.beans.PropertyChangeListener;
  72: import java.beans.PropertyVetoException;
  73: import java.beans.VetoableChangeListener;
  74: import java.io.Serializable;
  75: import java.util.EventListener;
  76: import java.util.Hashtable;
  77: import java.util.Locale;
  78: import java.util.Set;
  79: 
  80: import javax.accessibility.Accessible;
  81: import javax.accessibility.AccessibleContext;
  82: import javax.accessibility.AccessibleExtendedComponent;
  83: import javax.accessibility.AccessibleKeyBinding;
  84: import javax.accessibility.AccessibleRole;
  85: import javax.accessibility.AccessibleStateSet;
  86: import javax.swing.border.Border;
  87: import javax.swing.border.CompoundBorder;
  88: import javax.swing.border.TitledBorder;
  89: import javax.swing.event.AncestorEvent;
  90: import javax.swing.event.AncestorListener;
  91: import javax.swing.event.EventListenerList;
  92: import javax.swing.event.SwingPropertyChangeSupport;
  93: import javax.swing.plaf.ComponentUI;
  94: 
  95: /**
  96:  * The base class of all Swing components.
  97:  * It contains generic methods to manage events, properties and sizes. Actual
  98:  * drawing of the component is channeled to a look-and-feel class that is
  99:  * implemented elsewhere.
 100:  *
 101:  * @author Ronald Veldema (rveldema&064;cs.vu.nl)
 102:  * @author Graydon Hoare (graydon&064;redhat.com)
 103:  */
 104: public abstract class JComponent extends Container implements Serializable
 105: {
 106:   private static final long serialVersionUID = -7908749299918704233L;
 107: 
 108:   /** 
 109:    * Accessibility support is currently missing.
 110:    */
 111:   protected AccessibleContext accessibleContext;
 112: 
 113:   /**
 114:    * Basic accessibility support for <code>JComponent</code> derived
 115:    * widgets.
 116:    */
 117:   public abstract class AccessibleJComponent 
 118:     extends AccessibleAWTContainer
 119:     implements AccessibleExtendedComponent
 120:   {
 121:     /**
 122:      * Accessibility support for <code>JComponent</code>'s focus handler.
 123:      */
 124:     protected class AccessibleFocusHandler 
 125:       implements FocusListener
 126:     {
 127:       protected AccessibleFocusHandler()
 128:       {
 129:         // TODO: Implement this properly.
 130:       }
 131:       public void focusGained(FocusEvent event)
 132:       {
 133:         // TODO: Implement this properly.
 134:       }
 135:       public void focusLost(FocusEvent valevent)
 136:       {
 137:         // TODO: Implement this properly.
 138:       }
 139:     }
 140: 
 141:     /**
 142:      * Accessibility support for <code>JComponent</code>'s container handler.
 143:      */
 144:     protected class AccessibleContainerHandler 
 145:       implements ContainerListener
 146:     {
 147:       protected AccessibleContainerHandler()
 148:       {
 149:         // TODO: Implement this properly.
 150:       }
 151:       public void componentAdded(ContainerEvent event)
 152:       {
 153:         // TODO: Implement this properly.
 154:       }
 155:       public void componentRemoved(ContainerEvent valevent)
 156:       {
 157:         // TODO: Implement this properly.
 158:       }
 159:     }
 160: 
 161:     private static final long serialVersionUID = -7047089700479897799L;
 162:   
 163:     protected ContainerListener accessibleContainerHandler;
 164:     protected FocusListener accessibleFocusHandler;
 165: 
 166:     /**
 167:      * Manages the property change listeners;
 168:      */
 169:     private SwingPropertyChangeSupport changeSupport;
 170: 
 171:     protected AccessibleJComponent()
 172:     {
 173:       changeSupport = new SwingPropertyChangeSupport(this);
 174:     }
 175: 
 176:     /**
 177:      * Adds a property change listener to the list of registered listeners.
 178:      *
 179:      * @param listener the listener to add
 180:      */
 181:     public void addPropertyChangeListener(PropertyChangeListener listener)
 182:     {
 183:       changeSupport.addPropertyChangeListener(listener);
 184:     }
 185: 
 186:     /**
 187:      * Removes a propery change listener from the list of registered listeners.
 188:      *
 189:      * @param listener the listener to remove
 190:      */
 191:     public void removePropertyChangeListener(PropertyChangeListener listener)
 192:     {
 193:       changeSupport.removePropertyChangeListener(listener);
 194:     }
 195: 
 196:     /**
 197:      * Returns the number of accessible children of this object.
 198:      *
 199:      * @return  the number of accessible children of this object
 200:      */
 201:     public int getAccessibleChildrenCount()
 202:     {
 203:       int count = 0;
 204:       Component[] children = getComponents();
 205:       for (int i = 0; i < children.length; ++i)
 206:         {
 207:           if (children[i] instanceof Accessible)
 208:             count++;
 209:         }
 210:       return count;
 211:     }
 212: 
 213:     /**
 214:      * Returns the accessible child component at index <code>i</code>.
 215:      *
 216:      * @param i the index of the accessible child to return
 217:      *
 218:      * @return the accessible child component at index <code>i</code>
 219:      */
 220:     public Accessible getAccessibleChild(int i)
 221:     {
 222:       int index = 0;
 223:       Component[] children = getComponents();
 224:       Accessible found = null;
 225:       for (int j = 0; index != i; j++)
 226:         {
 227:           if (children[j] instanceof Accessible)
 228:             index++;
 229:           if (index == i)
 230:             found = (Accessible) children[index];
 231:         }
 232:       // TODO: Figure out what to do when i is not a valid index.
 233:       return found;
 234:     }
 235: 
 236:     /**
 237:      * Returns the accessible state set of this component.
 238:      *
 239:      * @return the accessible state set of this component
 240:      */
 241:     public AccessibleStateSet getAccessibleStateSet()
 242:     {
 243:       // FIXME: Figure out which states should be set here, and which are
 244:       // inherited from the super class.
 245:       return super.getAccessibleStateSet();
 246:     }
 247: 
 248:     /**
 249:      * Returns the localized name for this object. Generally this should
 250:      * almost never return {@link Component#getName()} since that is not
 251:      * a localized name. If the object is some kind of text component (like
 252:      * a menu item), then the value of the object may be returned. Also, if
 253:      * the object has a tooltip, the value of the tooltip may also be
 254:      * appropriate.
 255:      *
 256:      * @return the localized name for this object or <code>null</code> if this
 257:      *         object has no name
 258:      */
 259:     public String getAccessibleName()
 260:     {
 261:       // TODO: Figure out what exactly to return here. It's possible that this
 262:       // method simply should return null.
 263:       return null;
 264:     }
 265: 
 266:     /**
 267:      * Returns the localized description of this object.
 268:      *
 269:      * @return the localized description of this object or <code>null</code>
 270:      *         if this object has no description
 271:      */
 272:     public String getAccessibleDescription()
 273:     {
 274:       // TODO: Figure out what exactly to return here. It's possible that this
 275:       // method simply should return null.
 276:       return null;
 277:     }
 278: 
 279:     /**
 280:      * Returns the accessible role of this component.
 281:      *
 282:      * @return the accessible role of this component
 283:      *
 284:      * @see AccessibleRole
 285:      */
 286:     public AccessibleRole getAccessibleRole()
 287:     {
 288:       // TODO: Check if this is correct.
 289:       return AccessibleRole.SWING_COMPONENT;
 290:     }
 291: 
 292:     /**
 293:      * Recursivly searches a border hierarchy (starting at <code>border) for
 294:      * a titled border and returns the title if one is found, <code>null</code>
 295:      * otherwise.
 296:      *
 297:      * @param border the border to start search from
 298:      *
 299:      * @return the border title of a possibly found titled border
 300:      */
 301:     protected String getBorderTitle(Border border)
 302:     {
 303:       String title = null;
 304:       if (border instanceof CompoundBorder)
 305:         {
 306:           CompoundBorder compound = (CompoundBorder) border;
 307:           Border inner = compound.getInsideBorder();
 308:           title = getBorderTitle(inner);
 309:           if (title == null)
 310:             {
 311:               Border outer = compound.getOutsideBorder();
 312:               title = getBorderTitle(outer);
 313:             }
 314:         }
 315:       else if (border instanceof TitledBorder)
 316:         {
 317:           TitledBorder titled = (TitledBorder) border;
 318:           title = titled.getTitle(); 
 319:         }
 320:       return title;
 321:     }
 322: 
 323:     /**
 324:      * Returns the tooltip text for this accessible component.
 325:      *
 326:      * @return the tooltip text for this accessible component
 327:      */
 328:     public String getToolTipText()
 329:     {
 330:       return JComponent.this.getToolTipText();
 331:     }
 332: 
 333:     /**
 334:      * Returns the title of the border of this accessible component if
 335:      * this component has a titled border, otherwise returns <code>null</code>.
 336:      *
 337:      * @return the title of the border of this accessible component if
 338:      *         this component has a titled border, otherwise returns
 339:      *         <code>null</code>
 340:      */
 341:     public String getTitledBorderText()
 342:     {
 343:       return getBorderTitle(getBorder()); 
 344:     }
 345: 
 346:     /**
 347:      * Returns the keybindings associated with this accessible component or
 348:      * <code>null</code> if the component does not support key bindings.
 349:      *
 350:      * @return the keybindings associated with this accessible component
 351:      */
 352:     public AccessibleKeyBinding getAccessibleKeyBinding()
 353:     {
 354:       // TODO: Implement this properly.
 355:       return null;
 356:     }
 357:   }
 358: 
 359:   /** 
 360:    * An explicit value for the component's preferred size; if not set by a
 361:    * user, this is calculated on the fly by delegating to the {@link
 362:    * ComponentUI#getPreferredSize} method on the {@link #ui} property. 
 363:    */
 364:   Dimension preferredSize;
 365: 
 366:   /** 
 367:    * An explicit value for the component's minimum size; if not set by a
 368:    * user, this is calculated on the fly by delegating to the {@link
 369:    * ComponentUI#getMinimumSize} method on the {@link #ui} property. 
 370:    */
 371:   Dimension minimumSize;
 372: 
 373:   /** 
 374:    * An explicit value for the component's maximum size; if not set by a
 375:    * user, this is calculated on the fly by delegating to the {@link
 376:    * ComponentUI#getMaximumSize} method on the {@link #ui} property.
 377:    */
 378:   Dimension maximumSize;
 379: 
 380:   /**
 381:    * A value between 0.0 and 1.0 indicating the preferred horizontal
 382:    * alignment of the component, relative to its siblings. The values
 383:    * {@link #LEFT_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
 384:    * #RIGHT_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
 385:    * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
 386:    * managers use this property.
 387:    *
 388:    * @see #getAlignmentX
 389:    * @see #setAlignmentX
 390:    * @see javax.swing.OverlayLayout
 391:    * @see javax.swing.BoxLayout
 392:    */
 393:   float alignmentX = 0.5f;
 394: 
 395:   /**
 396:    * A value between 0.0 and 1.0 indicating the preferred vertical
 397:    * alignment of the component, relative to its siblings. The values
 398:    * {@link #TOP_ALIGNMENT}, {@link #CENTER_ALIGNMENT}, and {@link
 399:    * #BOTTOM_ALIGNMENT} can also be used, as synonyms for <code>0.0</code>,
 400:    * <code>0.5</code>, and <code>1.0</code>, respectively. Not all layout
 401:    * managers use this property.
 402:    *
 403:    * @see #getAlignmentY
 404:    * @see #setAlignmentY
 405:    * @see javax.swing.OverlayLayout
 406:    * @see javax.swing.BoxLayout
 407:    */
 408:   float alignmentY = 0.5f;
 409: 
 410:   /** 
 411:    * The border painted around this component.
 412:    * 
 413:    * @see #paintBorder
 414:    */
 415:   Border border;
 416: 
 417:   /** 
 418:    * The text to show in the tooltip associated with this component.
 419:    * 
 420:    * @see #setToolTipText
 421:    * @see #getToolTipText()
 422:    */
 423:    String toolTipText;
 424: 
 425:   /** 
 426:    * <p>Whether to double buffer this component when painting. This flag
 427:    * should generally be <code>true</code>, to ensure good painting
 428:    * performance.</p>
 429:    *
 430:    * <p>All children of a double buffered component are painted into the
 431:    * double buffer automatically, so only the top widget in a window needs
 432:    * to be double buffered.</p>
 433:    *
 434:    * @see #setDoubleBuffered
 435:    * @see #isDoubleBuffered
 436:    * @see #paint
 437:    */
 438:   boolean doubleBuffered = true;
 439: 
 440:   /**
 441:    * A set of flags indicating which debugging graphics facilities should
 442:    * be enabled on this component. The values should be a combination of
 443:    * {@link DebugGraphics#NONE_OPTION}, {@link DebugGraphics#LOG_OPTION},
 444:    * {@link DebugGraphics#FLASH_OPTION}, or {@link
 445:    * DebugGraphics#BUFFERED_OPTION}.
 446:    *
 447:    * @see #setDebugGraphicsOptions
 448:    * @see #getDebugGraphicsOptions
 449:    * @see DebugGraphics
 450:    * @see #getComponentGraphics
 451:    */
 452:   int debugGraphicsOptions;
 453: 
 454:   /** 
 455:    * <p>This property controls two independent behaviors simultaneously.</p>
 456:    *
 457:    * <p>First, it controls whether to fill the background of this widget
 458:    * when painting its body. This affects calls to {@link
 459:    * JComponent#paintComponent}, which in turn calls {@link
 460:    * ComponentUI#update} on the component's {@link #ui} property. If the
 461:    * component is opaque during this call, the background will be filled
 462:    * before calling {@link ComponentUI#paint}. This happens merely as a
 463:    * convenience; you may fill the component's background yourself too,
 464:    * but there is no need to do so if you will be filling with the same
 465:    * color.</p>
 466:    *
 467:    * <p>Second, it the opaque property informs swing's repaint system
 468:    * whether it will be necessary to paint the components "underneath" this
 469:    * component, in Z-order. If the component is opaque, it is considered to
 470:    * completely occlude components "underneath" it, so they will not be
 471:    * repainted along with the opaque component.</p>
 472:    *
 473:    * <p>The default value for this property is <code>false</code>, but most
 474:    * components will want to set it to <code>true</code> when installing UI
 475:    * defaults in {@link ComponentUI#installUI}.</p>
 476:    *
 477:    * @see #setOpaque
 478:    * @see #isOpaque
 479:    * @see #paintComponent
 480:    */
 481:   boolean opaque = false;
 482: 
 483:   /** 
 484:    * The user interface delegate for this component. Event delivery and
 485:    * repainting of the component are usually delegated to this object. 
 486:    *
 487:    * @see #setUI
 488:    * @see #getUIClassID
 489:    * @see #updateUI
 490:    */
 491:   protected ComponentUI ui;
 492: 
 493:   /**
 494:    * A hint to the focus system that this component should or should not
 495:    * get focus. If this is <code>false</code>, swing will not try to
 496:    * request focus on this component; if <code>true</code>, swing might
 497:    * try to request focus, but the request might fail. Thus it is only 
 498:    * a hint guiding swing's behavior.
 499:    *
 500:    * @see #requestFocus()
 501:    * @see #isRequestFocusEnabled
 502:    * @see #setRequestFocusEnabled
 503:    */
 504:   boolean requestFocusEnabled;
 505: 
 506:   /**
 507:    * Flag indicating behavior of this component when the mouse is dragged
 508:    * outside the component and the mouse <em>stops moving</em>. If
 509:    * <code>true</code>, synthetic mouse events will be delivered on regular
 510:    * timed intervals, continuing off in the direction the mouse exited the
 511:    * component, until the mouse is released or re-enters the component.
 512:    *
 513:    * @see #setAutoscrolls
 514:    * @see #getAutoscrolls
 515:    */
 516:   boolean autoscrolls = false;
 517: 
 518:   /**
 519:    * Indicates whether the current paint call is already double buffered or
 520:    * not. 
 521:    */
 522:   static boolean isPaintingDoubleBuffered = false;
 523: 
 524:   /**
 525:    * Listeners for events other than {@link PropertyChangeEvent} are
 526:    * handled by this listener list. PropertyChangeEvents are handled in
 527:    * {@link #changeSupport}.
 528:    */
 529:   protected EventListenerList listenerList = new EventListenerList();
 530: 
 531:   /** 
 532:    * Support for {@link PropertyChangeEvent} events. This is constructed
 533:    * lazily when the component gets its first {@link
 534:    * PropertyChangeListener} subscription; until then it's an empty slot.
 535:    */
 536:   private SwingPropertyChangeSupport changeSupport;
 537: 
 538: 
 539:   /** 
 540:    * Storage for "client properties", which are key/value pairs associated
 541:    * with this component by a "client", such as a user application or a
 542:    * layout manager. This is lazily constructed when the component gets its
 543:    * first client property.
 544:    */
 545:   private Hashtable clientProperties;
 546:   
 547:   private InputMap inputMap_whenFocused;
 548:   private InputMap inputMap_whenAncestorOfFocused;
 549:   private InputMap inputMap_whenInFocusedWindow;
 550:   private ActionMap actionMap;
 551:   /** @since 1.3 */
 552:   private boolean verifyInputWhenFocusTarget;
 553:   private InputVerifier inputVerifier;
 554: 
 555:   private TransferHandler transferHandler;
 556: 
 557:   /**
 558:    * A cached Rectangle object to be reused. Be careful when you use that,
 559:    * so that it doesn't get modified in another context within the same
 560:    * method call chain.
 561:    */
 562:   private static transient Rectangle rectCache;
 563: 
 564:   /**
 565:    * The default locale of the component.
 566:    * 
 567:    * @see #getDefaultLocale
 568:    * @see #setDefaultLocale
 569:    */
 570:   private static Locale defaultLocale;
 571:   
 572:   public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
 573: 
 574:   /**
 575:    * Constant used to indicate that no condition has been assigned to a
 576:    * particular action.
 577:    *
 578:    * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
 579:    */
 580:   public static final int UNDEFINED_CONDITION = -1;
 581: 
 582:   /**
 583:    * Constant used to indicate that an action should be performed only when 
 584:    * the component has focus.
 585:    *
 586:    * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
 587:    */
 588:   public static final int WHEN_FOCUSED = 0;
 589: 
 590:   /**
 591:    * Constant used to indicate that an action should be performed only when 
 592:    * the component is an ancestor of the component which has focus.
 593:    *
 594:    * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
 595:    */
 596:   public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
 597: 
 598:   /**
 599:    * Constant used to indicate that an action should be performed only when 
 600:    * the component is in the window which has focus.
 601:    *
 602:    * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
 603:    */
 604:   public static final int WHEN_IN_FOCUSED_WINDOW = 2;
 605: 
 606:   /**
 607:    * Indicates if this component is completely dirty or not. This is used
 608:    * by the RepaintManager's
 609:    * {@link RepaintManager#isCompletelyDirty(JComponent)} method.
 610:    */
 611:   boolean isCompletelyDirty = false;
 612: 
 613:   /**
 614:    * Creates a new <code>JComponent</code> instance.
 615:    */
 616:   public JComponent()
 617:   {
 618:     super();
 619:     super.setLayout(new FlowLayout());
 620:     setDropTarget(new DropTarget());
 621:     defaultLocale = Locale.getDefault();
 622:     debugGraphicsOptions = DebugGraphics.NONE_OPTION;
 623:     setRequestFocusEnabled(true);
 624:   }
 625: 
 626:   /**
 627:    * Helper to lazily construct and return the client properties table.
 628:    * 
 629:    * @return The current client properties table
 630:    *
 631:    * @see #clientProperties
 632:    * @see #getClientProperty
 633:    * @see #putClientProperty
 634:    */
 635:   private Hashtable getClientProperties()
 636:   {
 637:     if (clientProperties == null)
 638:       clientProperties = new Hashtable();
 639:     return clientProperties;
 640:   }
 641: 
 642:   /**
 643:    * Get a client property associated with this component and a particular
 644:    * key.
 645:    *
 646:    * @param key The key with which to look up the client property
 647:    *
 648:    * @return A client property associated with this object and key
 649:    *
 650:    * @see #clientProperties
 651:    * @see #getClientProperties
 652:    * @see #putClientProperty
 653:    */
 654:   public final Object getClientProperty(Object key)
 655:   {
 656:     return getClientProperties().get(key);
 657:   }
 658: 
 659:   /**
 660:    * Add a client property <code>value</code> to this component, associated
 661:    * with <code>key</code>. If there is an existing client property
 662:    * associated with <code>key</code>, it will be replaced.  A
 663:    * {@link PropertyChangeEvent} is sent to registered listeners (with the
 664:    * name of the property being <code>key.toString()</code>).
 665:    *
 666:    * @param key The key of the client property association to add
 667:    * @param value The value of the client property association to add
 668:    *
 669:    * @see #clientProperties
 670:    * @see #getClientProperties
 671:    * @see #getClientProperty
 672:    */
 673:   public final void putClientProperty(Object key, Object value)
 674:   {
 675:     Hashtable t = getClientProperties();
 676:     Object old = t.get(key);
 677:     if (value != null)
 678:       t.put(key, value);
 679:     else
 680:       t.remove(key);
 681:     firePropertyChange(key.toString(), old, value);
 682:   }
 683: 
 684:   /**
 685:    * Unregister an <code>AncestorListener</code>.
 686:    *
 687:    * @param listener The listener to unregister
 688:    * 
 689:    * @see #addAncestorListener
 690:    */
 691:   public void removeAncestorListener(AncestorListener listener)
 692:   {
 693:     listenerList.remove(AncestorListener.class, listener);
 694:   }
 695: 
 696:   /**
 697:    * Unregister a <code>PropertyChangeListener</code>.
 698:    *
 699:    * @param listener The listener to register
 700:    *
 701:    * @see #addPropertyChangeListener(PropertyChangeListener)
 702:    * @see #changeSupport
 703:    */
 704:   public void removePropertyChangeListener(PropertyChangeListener listener)
 705:   {
 706:     if (changeSupport != null)
 707:       changeSupport.removePropertyChangeListener(listener);
 708:   }
 709: 
 710:   /**
 711:    * Unregister a <code>PropertyChangeListener</code>.
 712:    *
 713:    * @param propertyName The property name to unregister the listener from
 714:    * @param listener The listener to unregister
 715:    *
 716:    * @see #addPropertyChangeListener(String, PropertyChangeListener)
 717:    * @see #changeSupport
 718:    */
 719:   public void removePropertyChangeListener(String propertyName,
 720:                                            PropertyChangeListener listener)
 721:   {
 722:     if (changeSupport != null)
 723:       changeSupport.removePropertyChangeListener(propertyName, listener);
 724:   }
 725: 
 726:   /**
 727:    * Unregister a <code>VetoableChangeChangeListener</code>.
 728:    *
 729:    * @param listener The listener to unregister
 730:    *
 731:    * @see #addVetoableChangeListener
 732:    */
 733:   public void removeVetoableChangeListener(VetoableChangeListener listener)
 734:   {
 735:     listenerList.remove(VetoableChangeListener.class, listener);
 736:   }
 737: 
 738:   /**
 739:    * Register an <code>AncestorListener</code>.
 740:    *
 741:    * @param listener The listener to register
 742:    *
 743:    * @see #removeVetoableChangeListener
 744:    */
 745:   public void addAncestorListener(AncestorListener listener)
 746:   {
 747:     listenerList.add(AncestorListener.class, listener);
 748:   }
 749: 
 750:   /**
 751:    * Register a <code>PropertyChangeListener</code>. This listener will
 752:    * receive any PropertyChangeEvent, regardless of property name. To
 753:    * listen to a specific property name, use {@link
 754:    * #addPropertyChangeListener(String,PropertyChangeListener)} instead.
 755:    *
 756:    * @param listener The listener to register
 757:    *
 758:    * @see #removePropertyChangeListener(PropertyChangeListener)
 759:    * @see #changeSupport
 760:    */
 761:   public void addPropertyChangeListener(PropertyChangeListener listener)
 762:   {
 763:     if (changeSupport == null)
 764:       changeSupport = new SwingPropertyChangeSupport(this);
 765:     changeSupport.addPropertyChangeListener(listener);
 766:   }
 767: 
 768:   /**
 769:    * Register a <code>PropertyChangeListener</code> for a specific, named
 770:    * property. To listen to all property changes, regardless of name, use
 771:    * {@link #addPropertyChangeListener(PropertyChangeListener)} instead.
 772:    *
 773:    * @param propertyName The property name to listen to
 774:    * @param listener The listener to register
 775:    *
 776:    * @see #removePropertyChangeListener(String, PropertyChangeListener)
 777:    * @see #changeSupport
 778:    */
 779:   public void addPropertyChangeListener(String propertyName,
 780:                                         PropertyChangeListener listener)
 781:   {
 782:     listenerList.add(PropertyChangeListener.class, listener);
 783:   }
 784: 
 785:   /**
 786:    * Register a <code>VetoableChangeListener</code>.
 787:    *
 788:    * @param listener The listener to register
 789:    *
 790:    * @see #removeVetoableChangeListener
 791:    * @see #listenerList
 792:    */
 793:   public void addVetoableChangeListener(VetoableChangeListener listener)
 794:   {
 795:     listenerList.add(VetoableChangeListener.class, listener);
 796:   }
 797: 
 798:   /**
 799:    * Return all registered listeners of a particular type.
 800:    *
 801:    * @param listenerType The type of listener to return
 802:    *
 803:    * @return All listeners in the {@link #listenerList} which 
 804:    * are of the specified type
 805:    *
 806:    * @see #listenerList
 807:    */
 808:   public EventListener[] getListeners(Class listenerType)
 809:   {
 810:     return listenerList.getListeners(listenerType);
 811:   }
 812: 
 813:   /**
 814:    * Return all registered <code>AncestorListener</code> objects.
 815:    *
 816:    * @return The set of <code>AncestorListener</code> objects in {@link
 817:    * #listenerList}
 818:    */
 819:   public AncestorListener[] getAncestorListeners()
 820:   {
 821:     return (AncestorListener[]) getListeners(AncestorListener.class);
 822:   }
 823: 
 824:   /**
 825:    * Return all registered <code>VetoableChangeListener</code> objects.
 826:    *
 827:    * @return The set of <code>VetoableChangeListener</code> objects in {@link
 828:    * #listenerList}
 829:    */
 830:   public VetoableChangeListener[] getVetoableChangeListeners()
 831:   {
 832:     return (VetoableChangeListener[]) getListeners(VetoableChangeListener.class);
 833:   }
 834: 
 835:   /**
 836:    * Return all <code>PropertyChangeListener</code> objects registered to listen
 837:    * for a particular property.
 838:    *
 839:    * @param property The property to return the listeners of
 840:    *
 841:    * @return The set of <code>PropertyChangeListener</code> objects in 
 842:    *     {@link #changeSupport} registered to listen on the specified property
 843:    */
 844:   public PropertyChangeListener[] getPropertyChangeListeners(String property)
 845:   {
 846:     return changeSupport == null ? new PropertyChangeListener[0]
 847:                           : changeSupport.getPropertyChangeListeners(property);
 848:   }
 849: 
 850:   /**
 851:    * A variant of {@link #firePropertyChange(String,Object,Object)} 
 852:    * for properties with <code>boolean</code> values.
 853:    */
 854:   public void firePropertyChange(String propertyName, boolean oldValue,
 855:                                  boolean newValue)
 856:   {
 857:     if (changeSupport != null)
 858:       changeSupport.firePropertyChange(propertyName, Boolean.valueOf(oldValue),
 859:                                        Boolean.valueOf(newValue));
 860:   }
 861: 
 862:   /**
 863:    * A variant of {@link #firePropertyChange(String,Object,Object)} 
 864:    * for properties with <code>byte</code> values.
 865:    */
 866:   public void firePropertyChange(String propertyName, byte oldValue,
 867:                                  byte newValue)
 868:   {
 869:     if (changeSupport != null)
 870:       changeSupport.firePropertyChange(propertyName, new Byte(oldValue),
 871:                                        new Byte(newValue));
 872:   }
 873: 
 874:   /**
 875:    * A variant of {@link #firePropertyChange(String,Object,Object)} 
 876:    * for properties with <code>char</code> values.
 877:    */
 878:   public void firePropertyChange(String propertyName, char oldValue,
 879:                                  char newValue)
 880:   {
 881:     if (changeSupport != null)
 882:       changeSupport.firePropertyChange(propertyName, new Character(oldValue),
 883:                                        new Character(newValue));
 884:   }
 885: 
 886:   /**
 887:    * A variant of {@link #firePropertyChange(String,Object,Object)} 
 888:    * for properties with <code>double</code> values.
 889:    */
 890:   public void firePropertyChange(String propertyName, double oldValue,
 891:                                  double newValue)
 892:   {
 893:     if (changeSupport != null)
 894:       changeSupport.firePropertyChange(propertyName, new Double(oldValue),
 895:                                        new Double(newValue));
 896:   }
 897: 
 898:   /**
 899:    * A variant of {@link #firePropertyChange(String,Object,Object)} 
 900:    * for properties with <code>float</code> values.
 901:    */
 902:   public void firePropertyChange(String propertyName, float oldValue,
 903:                                  float newValue)
 904:   {
 905:     if (changeSupport != null)
 906:       changeSupport.firePropertyChange(propertyName, new Float(oldValue),
 907:                                        new Float(newValue));
 908:   }
 909: 
 910:   /**
 911:    * A variant of {@link #firePropertyChange(String,Object,Object)} 
 912:    * for properties with <code>int</code> values.
 913:    */
 914:   public void firePropertyChange(String propertyName, int oldValue,
 915:                                  int newValue)
 916:   {
 917:     if (changeSupport != null)
 918:       changeSupport.firePropertyChange(propertyName, new Integer(oldValue),
 919:                                        new Integer(newValue));
 920:   }
 921: 
 922:   /**
 923:    * A variant of {@link #firePropertyChange(String,Object,Object)} 
 924:    * for properties with <code>long</code> values.
 925:    */
 926:   public void firePropertyChange(String propertyName, long oldValue,
 927:                                  long newValue)
 928:   {
 929:     if (changeSupport != null)
 930:       changeSupport.firePropertyChange(propertyName, new Long(oldValue),
 931:                                        new Long(newValue));
 932:   }
 933: 
 934:   /**
 935:    * Call {@link PropertyChangeListener#propertyChange} on all listeners
 936:    * registered to listen to a given property. Any method which changes
 937:    * the specified property of this component should call this method.
 938:    *
 939:    * @param propertyName The property which changed
 940:    * @param oldValue The old value of the property
 941:    * @param newValue The new value of the property
 942:    *
 943:    * @see #changeSupport
 944:    * @see #addPropertyChangeListener(PropertyChangeListener)
 945:    * @see #removePropertyChangeListener(PropertyChangeListener)
 946:    */
 947:   protected void firePropertyChange(String propertyName, Object oldValue,
 948:                                     Object newValue)
 949:   {
 950:     if (changeSupport != null)
 951:       changeSupport.firePropertyChange(propertyName, oldValue, newValue);
 952:   }
 953: 
 954:   /**
 955:    * A variant of {@link #firePropertyChange(String,Object,Object)} 
 956:    * for properties with <code>short</code> values.
 957:    */
 958:   public void firePropertyChange(String propertyName, short oldValue,
 959:                                  short newValue)
 960:   {
 961:     if (changeSupport != null)
 962:       changeSupport.firePropertyChange(propertyName, new Short(oldValue),
 963:                                        new Short(newValue));
 964:   }
 965: 
 966:   /**
 967:    * Call {@link VetoableChangeListener#vetoableChange} on all listeners
 968:    * registered to listen to a given property. Any method which changes
 969:    * the specified property of this component should call this method.
 970:    *
 971:    * @param propertyName The property which changed
 972:    * @param oldValue The old value of the property
 973:    * @param newValue The new value of the property
 974:    *
 975:    * @throws PropertyVetoException if the change was vetoed by a listener
 976:    *
 977:    * @see #addVetoableChangeListener
 978:    * @see #removeVetoableChangeListener
 979:    */
 980:   protected void fireVetoableChange(String propertyName, Object oldValue,
 981:                                     Object newValue)
 982:     throws PropertyVetoException
 983:   {
 984:     VetoableChangeListener[] listeners = getVetoableChangeListeners();
 985: 
 986:     PropertyChangeEvent evt = new PropertyChangeEvent(this, propertyName, oldValue, newValue);
 987: 
 988:     for (int i = 0; i < listeners.length; i++)
 989:       listeners[i].vetoableChange(evt);
 990:   }
 991: 
 992:   /**
 993:    * Get the value of the accessibleContext property for this component.
 994:    *
 995:    * @return the current value of the property
 996:    */
 997:   public AccessibleContext getAccessibleContext()
 998:   {
 999:     return null;
1000:   }
1001: 
1002:   /**
1003:    * Get the value of the {@link #alignmentX} property.
1004:    *
1005:    * @return The current value of the property.
1006:    *
1007:    * @see #setAlignmentX
1008:    * @see #alignmentY
1009:    */
1010:   public float getAlignmentX()
1011:   {
1012:     return alignmentX;
1013:   }
1014: 
1015:   /**
1016:    * Get the value of the {@link #alignmentY} property.
1017:    *
1018:    * @return The current value of the property.
1019:    *
1020:    * @see #setAlignmentY
1021:    * @see #alignmentX
1022:    */
1023:   public float getAlignmentY()
1024:   {
1025:     return alignmentY;
1026:   }
1027: 
1028:   /**
1029:    * Get the current value of the {@link #autoscrolls} property.
1030:    *
1031:    * @return The current value of the property
1032:    */
1033:   public boolean getAutoscrolls()
1034:   {
1035:     return autoscrolls;
1036:   }
1037: 
1038:   /**
1039:    * Set the value of the {@link #border} property.
1040:    *   
1041:    * @param newBorder The new value of the property
1042:    *
1043:    * @see #getBorder
1044:    */
1045:   public void setBorder(Border newBorder)
1046:   {
1047:     Border oldBorder = getBorder();
1048:     if (oldBorder == newBorder)
1049:       return;
1050: 
1051:     border = newBorder;
1052:     firePropertyChange("border", oldBorder, newBorder);
1053:     repaint();
1054:   }
1055: 
1056:   /**
1057:    * Get the value of the {@link #border} property.
1058:    *
1059:    * @return The property's current value
1060:    *
1061:    * @see #setBorder
1062:    */
1063:   public Border getBorder()
1064:   {
1065:     return border;
1066:   }
1067: 
1068:   /**
1069:    * Get the component's current bounding box. If a rectangle is provided,
1070:    * use this as the return value (adjusting its fields in place);
1071:    * otherwise (of <code>null</code> is provided) return a new {@link
1072:    * Rectangle}.
1073:    *
1074:    * @param rv Optional return value to use
1075:    *
1076:    * @return A rectangle bounding the component
1077:    */
1078:   public Rectangle getBounds(Rectangle rv)
1079:   {
1080:     if (rv == null)
1081:       return new Rectangle(getX(), getY(), getWidth(), getHeight());
1082:     else
1083:       {
1084:         rv.setBounds(getX(), getY(), getWidth(), getHeight());
1085:         return rv;
1086:       }
1087:   }
1088: 
1089:   /**
1090:    * Prepares a graphics context for painting this object. If {@link
1091:    * #debugGraphicsOptions} is not equal to {@link
1092:    * DebugGraphics#NONE_OPTION}, produce a new {@link DebugGraphics} object
1093:    * wrapping the parameter. Otherwise configure the parameter with this
1094:    * component's foreground color and font.
1095:    *
1096:    * @param g The graphics context to wrap or configure
1097:    *
1098:    * @return A graphics context to paint this object with
1099:    *
1100:    * @see #debugGraphicsOptions
1101:    * @see #paint
1102:    */
1103:   protected Graphics getComponentGraphics(Graphics g)
1104:   {
1105:     Graphics g2 = g;
1106:     int options = getDebugGraphicsOptions();
1107:     if (options != DebugGraphics.NONE_OPTION)
1108:       {
1109:         if (!(g2 instanceof DebugGraphics))
1110:           g2 = new DebugGraphics(g);
1111:         DebugGraphics dg = (DebugGraphics) g2;
1112:         dg.setDebugOptions(dg.getDebugOptions() | options);
1113:       }
1114:     g2.setFont(this.getFont());
1115:     g2.setColor(this.getForeground());
1116:     return g2;
1117:   }
1118: 
1119:   /**
1120:    * Get the value of the {@link #debugGraphicsOptions} property.
1121:    *
1122:    * @return The current value of the property.
1123:    *
1124:    * @see #setDebugGraphicsOptions
1125:    * @see #debugGraphicsOptions
1126:    */
1127:   public int getDebugGraphicsOptions()
1128:   {
1129:     String option = System.getProperty("gnu.javax.swing.DebugGraphics");
1130:     int options = debugGraphicsOptions;
1131:     if (option != null && option.length() != 0)
1132:       {
1133:         if (options < 0)
1134:           options = 0;
1135: 
1136:         if (option.equals("LOG"))
1137:           options |= DebugGraphics.LOG_OPTION;
1138:         else if (option.equals("FLASH"))
1139:           options |= DebugGraphics.FLASH_OPTION;
1140:       }
1141:     return options;
1142:   }
1143: 
1144:   /**
1145:    * Get the component's insets, which are calculated from
1146:    * the {@link #border} property. If the border is <code>null</code>,
1147:    * calls {@link Container#getInsets}.
1148:    *
1149:    * @return The component's current insets
1150:    */
1151:   public Insets getInsets()
1152:   {
1153:     if (border == null)
1154:       return super.getInsets();
1155:     return getBorder().getBorderInsets(this);
1156:   }
1157: 
1158:   /**
1159:    * Get the component's insets, which are calculated from the {@link
1160:    * #border} property. If the border is <code>null</code>, calls {@link
1161:    * Container#getInsets}. The passed-in {@link Insets} value will be
1162:    * used as the return value, if possible.
1163:    *
1164:    * @param insets Return value object to reuse, if possible
1165:    *
1166:    * @return The component's current insets
1167:    */
1168:   public Insets getInsets(Insets insets)
1169:   {
1170:     Insets t = getInsets();
1171: 
1172:     if (insets == null)
1173:       return t;
1174: 
1175:     insets.left = t.left;
1176:     insets.right = t.right;
1177:     insets.top = t.top;
1178:     insets.bottom = t.bottom;
1179:     return insets;
1180:   }
1181: 
1182:   /**
1183:    * Get the component's location. The passed-in {@link Point} value
1184:    * will be used as the return value, if possible.
1185:    *
1186:    * @param rv Return value object to reuse, if possible
1187:    *
1188:    * @return The component's current location
1189:    */
1190:   public Point getLocation(Point rv)
1191:   {
1192:     if (rv == null)
1193:       return new Point(getX(), getY());
1194: 
1195:     rv.setLocation(getX(), getY());
1196:     return rv;
1197:   }
1198: 
1199:   /**
1200:    * Get the component's maximum size. If the {@link #maximumSize} property
1201:    * has been explicitly set, it is returned. If the {@link #maximumSize}
1202:    * property has not been set but the {@link #ui} property has been, the
1203:    * result of {@link ComponentUI#getMaximumSize} is returned. If neither
1204:    * property has been set, the result of {@link Container#getMaximumSize}
1205:    * is returned.
1206:    *
1207:    * @return The maximum size of the component
1208:    *
1209:    * @see #maximumSize
1210:    * @see #setMaximumSize
1211:    */
1212:   public Dimension getMaximumSize()
1213:   {
1214:     if (maximumSize != null)
1215:       return maximumSize;
1216: 
1217:     if (ui != null)
1218:       {
1219:         Dimension s = ui.getMaximumSize(this);
1220:         if (s != null)
1221:           return s;
1222:       }
1223: 
1224:     Dimension p = super.getMaximumSize();
1225:     return p;
1226:   }
1227: 
1228:   /**
1229:    * Get the component's minimum size. If the {@link #minimumSize} property
1230:    * has been explicitly set, it is returned. If the {@link #minimumSize}
1231:    * property has not been set but the {@link #ui} property has been, the
1232:    * result of {@link ComponentUI#getMinimumSize} is returned. If neither
1233:    * property has been set, the result of {@link Container#getMinimumSize}
1234:    * is returned.
1235:    *
1236:    * @return The minimum size of the component
1237:    *
1238:    * @see #minimumSize
1239:    * @see #setMinimumSize
1240:    */
1241:   public Dimension getMinimumSize()
1242:   {
1243:     if (minimumSize != null)
1244:       return minimumSize;
1245: 
1246:     if (ui != null)
1247:       {
1248:         Dimension s = ui.getMinimumSize(this);
1249:         if (s != null)
1250:           return s;
1251:       }
1252: 
1253:     Dimension p = super.getMinimumSize();
1254:     return p;
1255:   }
1256: 
1257:   /**
1258:    * Get the component's preferred size. If the {@link #preferredSize}
1259:    * property has been explicitly set, it is returned. If the {@link
1260:    * #preferredSize} property has not been set but the {@link #ui} property
1261:    * has been, the result of {@link ComponentUI#getPreferredSize} is
1262:    * returned. If neither property has been set, the result of {@link
1263:    * Container#getPreferredSize} is returned.
1264:    *
1265:    * @return The preferred size of the component
1266:    *
1267:    * @see #preferredSize
1268:    * @see #setPreferredSize
1269:    */
1270:   public Dimension getPreferredSize()
1271:   {
1272:     Dimension prefSize = null;
1273:     if (preferredSize != null)
1274:       prefSize = preferredSize;
1275: 
1276:     else if (ui != null)
1277:       {
1278:         Dimension s = ui.getPreferredSize(this);
1279:         if (s != null)
1280:           prefSize = s;
1281:       }
1282: 
1283:     if (prefSize == null)
1284:       prefSize = super.getPreferredSize();
1285:     // make sure that prefSize is not smaller than minSize
1286:     if (minimumSize != null && prefSize != null
1287:         && (minimumSize.width > prefSize.width
1288:             || minimumSize.height > prefSize.height))
1289:         prefSize = new Dimension(Math.max(minimumSize.width, prefSize.width),
1290:                                  Math.max(minimumSize.height, prefSize.height));
1291:     return prefSize;
1292:   }
1293: 
1294:   /**
1295:    * Checks if a maximum size was explicitely set on the component.
1296:    *
1297:    * @return <code>true</code> if a maximum size was set,
1298:    * <code>false</code> otherwise
1299:    * 
1300:    * @since 1.3
1301:    */
1302:   public boolean isMaximumSizeSet()
1303:   {
1304:     return maximumSize != null;
1305:   }
1306: 
1307:   /**
1308:    * Checks if a minimum size was explicitely set on the component.
1309:    *
1310:    * @return <code>true</code> if a minimum size was set,
1311:    * <code>false</code> otherwise
1312:    * 
1313:    * @since 1.3
1314:    */
1315:   public boolean isMinimumSizeSet()
1316:   {
1317:     return minimumSize != null;
1318:   }
1319: 
1320:   /**
1321:    * Checks if a preferred size was explicitely set on the component.
1322:    *
1323:    * @return <code>true</code> if a preferred size was set,
1324:    * <code>false</code> otherwise
1325:    * 
1326:    * @since 1.3
1327:    */
1328:   public boolean isPreferredSizeSet()
1329:   {
1330:     return preferredSize != null;
1331:   }
1332:   
1333:   /**
1334:    * Return the value of the <code>nextFocusableComponent</code> property.
1335:    *
1336:    * @return The current value of the property, or <code>null</code>
1337:    * if none has been set.
1338:    * 
1339:    * @deprecated See {@link java.awt.FocusTraversalPolicy}
1340:    */
1341:   public Component getNextFocusableComponent()
1342:   {
1343:     return null;
1344:   }
1345: 
1346:   /**
1347:    * Return the set of {@link KeyStroke} objects which are registered
1348:    * to initiate actions on this component.
1349:    *
1350:    * @return An array of the registered keystrokes
1351:    */
1352:   public KeyStroke[] getRegisteredKeyStrokes()
1353:   {
1354:     return null;
1355:   }
1356: 
1357:   /**
1358:    * Returns the first ancestor of this component which is a {@link JRootPane}.
1359:    * Equivalent to calling <code>SwingUtilities.getRootPane(this);</code>.
1360:    *
1361:    * @return An ancestral JRootPane, or <code>null</code> if none exists.
1362:    */
1363:   public JRootPane getRootPane()
1364:   {
1365:     JRootPane p = SwingUtilities.getRootPane(this);
1366:     return p;
1367:   }
1368: 
1369:   /**
1370:    * Get the component's size. The passed-in {@link Dimension} value
1371:    * will be used as the return value, if possible.
1372:    *
1373:    * @param rv Return value object to reuse, if possible
1374:    *
1375:    * @return The component's current size
1376:    */
1377:   public Dimension getSize(Dimension rv)
1378:   {
1379:     if (rv == null)
1380:       return new Dimension(getWidth(), getHeight());
1381:     else
1382:       {
1383:         rv.setSize(getWidth(), getHeight());
1384:         return rv;
1385:       }
1386:   }
1387: 
1388:   /**
1389:    * Return the <code>toolTip</code> property of this component, creating it and
1390:    * setting it if it is currently <code>null</code>. This method can be
1391:    * overridden in subclasses which wish to control the exact form of
1392:    * tooltip created.
1393:    *
1394:    * @return The current toolTip
1395:    */
1396:   public JToolTip createToolTip()
1397:   {
1398:     JToolTip toolTip = new JToolTip();
1399:     toolTip.setComponent(this);
1400:     toolTip.setTipText(toolTipText);
1401: 
1402:     return toolTip;
1403:   }
1404: 
1405:   /**
1406:    * Return the location at which the {@link #toolTipText} property should be
1407:    * displayed, when triggered by a particular mouse event. 
1408:    *
1409:    * @param event The event the tooltip is being presented in response to
1410:    *
1411:    * @return The point at which to display a tooltip, or <code>null</code>
1412:    *     if swing is to choose a default location.
1413:    */
1414:   public Point getToolTipLocation(MouseEvent event)
1415:   {
1416:     return null;
1417:   }
1418: 
1419:   /**
1420:    * Set the value of the {@link #toolTipText} property.
1421:    *
1422:    * @param text The new property value
1423:    *
1424:    * @see #getToolTipText()
1425:    */
1426:   public void setToolTipText(String text)
1427:   {
1428:     if (text == null)
1429:     {
1430:       ToolTipManager.sharedInstance().unregisterComponent(this);
1431:       toolTipText = null;
1432:       return;
1433:     }
1434: 
1435:     // XXX: The tip text doesn't get updated unless you set it to null
1436:     // and then to something not-null. This is consistent with the behaviour
1437:     // of Sun's ToolTipManager.
1438: 
1439:     String oldText = toolTipText;
1440:     toolTipText = text;
1441: 
1442:     if (oldText == null)
1443:       ToolTipManager.sharedInstance().registerComponent(this);
1444:   }
1445: 
1446:   /**
1447:    * Get the value of the {@link #toolTipText} property.
1448:    *
1449:    * @return The current property value
1450:    *
1451:    * @see #setToolTipText
1452:    */
1453:   public String getToolTipText()
1454:   {
1455:     return toolTipText;
1456:   }
1457: 
1458:   /**
1459:    * Get the value of the {@link #toolTipText} property, in response to a
1460:    * particular mouse event.
1461:    *
1462:    * @param event The mouse event which triggered the tooltip
1463:    *
1464:    * @return The current property value
1465:    *
1466:    * @see #setToolTipText
1467:    */
1468:   public String getToolTipText(MouseEvent event)
1469:   {
1470:     return getToolTipText();
1471:   }
1472: 
1473:   /**
1474:    * Return the top level ancestral container (usually a {@link
1475:    * java.awt.Window} or {@link java.applet.Applet}) which this component is
1476:    * contained within, or <code>null</code> if no ancestors exist.
1477:    *
1478:    * @return The top level container, if it exists
1479:    */
1480:   public Container getTopLevelAncestor()
1481:   {
1482:     Container c = getParent();
1483:     for (Container peek = c; peek != null; peek = peek.getParent())
1484:       c = peek;
1485:     return c;
1486:   }
1487: 
1488:   /**
1489:    * Compute the component's visible rectangle, which is defined
1490:    * recursively as either the component's bounds, if it has no parent, or
1491:    * the intersection of the component's bounds with the visible rectangle
1492:    * of its parent.
1493:    *
1494:    * @param rect The return value slot to place the visible rectangle in
1495:    */
1496:   public void computeVisibleRect(Rectangle rect)
1497:   {
1498:     Component c = getParent();
1499:     if (c != null && c instanceof JComponent)
1500:       {
1501:         ((JComponent) c).computeVisibleRect(rect);
1502:         rect.translate(-getX(), -getY());
1503:         Rectangle2D.intersect(rect,
1504:                               new Rectangle(0, 0, getWidth(), getHeight()),
1505:                               rect);
1506:       }
1507:     else
1508:       rect.setRect(0, 0, getWidth(), getHeight());
1509:   }
1510: 
1511:   /**
1512:    * Return the component's visible rectangle in a new {@link Rectangle},
1513:    * rather than via a return slot.
1514:    *
1515:    * @return The component's visible rectangle
1516:    *
1517:    * @see #computeVisibleRect(Rectangle)
1518:    */
1519:   public Rectangle getVisibleRect()
1520:   {
1521:     Rectangle r = new Rectangle();
1522:     computeVisibleRect(r);
1523:     return r;
1524:   }
1525: 
1526:   /**
1527:    * <p>Requests that this component receive input focus, giving window
1528:    * focus to the top level ancestor of this component. Only works on
1529:    * displayable, focusable, visible components.</p>
1530:    *
1531:    * <p>This method should not be called by clients; it is intended for
1532:    * focus implementations. Use {@link Component#requestFocus()} instead.</p>
1533:    *
1534:    * @see Component#requestFocus()
1535:    */
1536:   public void grabFocus()
1537:   {
1538:     // TODO: Implement this properly.
1539:   }
1540: 
1541:   /**
1542:    * Get the value of the {@link #doubleBuffered} property.
1543:    *
1544:    * @return The property's current value
1545:    */
1546:   public boolean isDoubleBuffered()
1547:   {
1548:     return doubleBuffered;
1549:   }
1550: 
1551:   /**
1552:    * Return <code>true</code> if the provided component has no native peer;
1553:    * in other words, if it is a "lightweight component".
1554:    *
1555:    * @param c The component to test for lightweight-ness
1556:    *
1557:    * @return Whether or not the component is lightweight
1558:    */
1559:   public static boolean isLightweightComponent(Component c)
1560:   {
1561:     return c.getPeer() instanceof LightweightPeer;
1562:   }
1563: 
1564:   /**
1565:    * Return <code>true</code> if you wish this component to manage its own
1566:    * focus. In particular: if you want this component to be sent
1567:    * <code>TAB</code> and <code>SHIFT+TAB</code> key events, and to not
1568:    * have its children considered as focus transfer targets. If
1569:    * <code>true</code>, focus traversal around this component changes to
1570:    * <code>CTRL+TAB</code> and <code>CTRL+SHIFT+TAB</code>.
1571:    *
1572:    * @return <code>true</code> if you want this component to manage its own
1573:    *     focus, otherwise (by default) <code>false</code>
1574:    *
1575:    * @deprecated 1.4 Use {@link Component#setFocusTraversalKeys(int, Set)} and
1576:    *     {@link Container#setFocusCycleRoot(boolean)} instead
1577:    */
1578:   public boolean isManagingFocus()
1579:   {
1580:     return false;
1581:   }
1582: 
1583:   /**
1584:    * Return the current value of the {@link #opaque} property. 
1585:    *
1586:    * @return The current property value
1587:    */
1588:   public boolean isOpaque()
1589:   {
1590:     return opaque;
1591:   }
1592: 
1593:   /**
1594:    * Return <code>true</code> if the component can guarantee that none of its
1595:    * children will overlap in Z-order. This is a hint to the painting system.
1596:    * The default is to return <code>true</code>, but some components such as
1597:    * {@link JLayeredPane} should override this to return <code>false</code>.
1598:    *
1599:    * @return Whether the component tiles its children
1600:    */
1601:   public boolean isOptimizedDrawingEnabled()
1602:   {
1603:     return true;
1604:   }
1605: 
1606:   /**
1607:    * Return <code>true</code> if this component is currently painting a tile.
1608:    *
1609:    * @return Whether the component is painting a tile
1610:    */
1611:   public boolean isPaintingTile()
1612:   {
1613:     return false;
1614:   }
1615: 
1616:   /**
1617:    * Get the value of the {@link #requestFocusEnabled} property.
1618:    *
1619:    * @return The current value of the property
1620:    */
1621:   public boolean isRequestFocusEnabled()
1622:   {
1623:     return requestFocusEnabled;
1624:   }
1625: 
1626:   /**
1627:    * Return <code>true</code> if this component is a validation root; this
1628:    * will cause calls to {@link #invalidate()} in this component's children
1629:    * to be "captured" at this component, and not propagate to its parents.
1630:    * For most components this should return <code>false</code>, but some
1631:    * components such as {@link JViewport} will want to return
1632:    * <code>true</code>.
1633:    *
1634:    * @return Whether this component is a validation root
1635:    */
1636:   public boolean isValidateRoot()
1637:   {
1638:     return false;
1639:   }
1640: 
1641:   /**
1642:    * <p>Paint the component. This is a delicate process, and should only be
1643:    * called from the repaint thread, under control of the {@link
1644:    * RepaintManager}. Client code should usually call {@link #repaint()} to
1645:    * trigger painting.</p>
1646:    *
1647:    * <p>The body of the <code>paint</code> call involves calling {@link
1648:    * #paintComponent}, {@link #paintBorder}, and {@link #paintChildren} in
1649:    * order. If you want to customize painting behavior, you should override
1650:    * one of these methods rather than <code>paint</code>.</p>
1651:    *
1652:    * <p>For more details on the painting sequence, see <a
1653:    * href="http://java.sun.com/products/jfc/tsc/articles/painting/index.html">
1654:    * this article</a>.</p>
1655:    *
1656:    * @param g The graphics context to paint with
1657:    *
1658:    * @see #paintImmediately(Rectangle)
1659:    */
1660:   public void paint(Graphics g)
1661:   {
1662:     RepaintManager rm = RepaintManager.currentManager(this);
1663:     // We do a little stunt act here to switch on double buffering if it's
1664:     // not already on. If we are not already doublebuffered, then we jump
1665:     // into the method paintDoubleBuffered, which turns on the double buffer
1666:     // and then calls paint(g) again. In the second call we go into the else
1667:     // branch of this if statement and actually paint things to the double
1668:     // buffer. When this method completes, the call stack unwinds back to
1669:     // paintDoubleBuffered, where the buffer contents is finally drawn to the
1670:     // screen.
1671:     if (!isPaintingDoubleBuffered && isDoubleBuffered()
1672:         && rm.isDoubleBufferingEnabled())
1673:       paintDoubleBuffered(g);
1674:     else
1675:       {
1676:         if (g.getClip() == null)
1677:           g.setClip(0, 0, getWidth(), getHeight());
1678:         paintComponent(g);
1679:         paintBorder(g);
1680:         paintChildren(g);
1681:         Rectangle clip = g.getClipBounds();
1682:         if (clip.x == 0 && clip.y == 0 && clip.width == getWidth()
1683:             && clip.height == getHeight())
1684:           RepaintManager.currentManager(this).markCompletelyClean(this);
1685:       }
1686:   }
1687: 
1688:   /**
1689:    * Paint the component's border. This usually means calling {@link
1690:    * Border#paintBorder} on the {@link #border} property, if it is
1691:    * non-<code>null</code>. You may override this if you wish to customize
1692:    * border painting behavior. The border is painted after the component's
1693:    * body, but before the component's children.
1694:    *
1695:    * @param g The graphics context with which to paint the border
1696:    *
1697:    * @see #paint
1698:    * @see #paintChildren
1699:    * @see #paintComponent
1700:    */
1701:   protected void paintBorder(Graphics g)
1702:   {
1703:     if (getBorder() != null)
1704:       getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight());
1705:   }
1706: 
1707:   /**
1708:    * Paint the component's children. This usually means calling {@link
1709:    * Container#paint}, which recursively calls {@link #paint} on any of the
1710:    * component's children, with appropriate changes to coordinate space and
1711:    * clipping region. You may override this if you wish to customize
1712:    * children painting behavior. The children are painted after the
1713:    * component's body and border.
1714:    *
1715:    * @param g The graphics context with which to paint the children
1716:    *
1717:    * @see #paint
1718:    * @see #paintBorder
1719:    * @see #paintComponent
1720:    */
1721:   protected void paintChildren(Graphics g)
1722:   {
1723:     Shape originalClip = g.getClip();
1724:     Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache);
1725:     g.clipRect(inner.x, inner.y, inner.width, inner.height);
1726:     Component[] children = getComponents();
1727:     for (int i = children.length - 1; i >= 0; --i)
1728:       {
1729:         if (!children[i].isVisible())
1730:           continue;
1731: 
1732:         Rectangle bounds = children[i].getBounds(rectCache);
1733:         Rectangle oldClip = g.getClipBounds();
1734:         if (oldClip == null)
1735:           oldClip = bounds;
1736: 
1737:         if (!g.hitClip(bounds.x, bounds.y, bounds.width, bounds.height))
1738:           continue;
1739: 
1740:         boolean translated = false;
1741:         try
1742:           {
1743:             g.clipRect(bounds.x, bounds.y, bounds.width, bounds.height);
1744:             g.translate(bounds.x, bounds.y);
1745:             translated = true;
1746:             children[i].paint(g);
1747:           }
1748:         finally
1749:           {
1750:             if (translated)
1751:               g.translate(-bounds.x, -bounds.y);
1752:             g.setClip(oldClip);
1753:           }
1754:       }
1755:     g.setClip(originalClip);
1756:   }
1757: 
1758:   /**
1759:    * Paint the component's body. This usually means calling {@link
1760:    * ComponentUI#update} on the {@link #ui} property of the component, if
1761:    * it is non-<code>null</code>. You may override this if you wish to
1762:    * customize the component's body-painting behavior. The component's body
1763:    * is painted first, before the border and children.
1764:    *
1765:    * @param g The graphics context with which to paint the body
1766:    *
1767:    * @see #paint
1768:    * @see #paintBorder
1769:    * @see #paintChildren
1770:    */
1771:   protected void paintComponent(Graphics g)
1772:   {
1773:     if (ui != null)
1774:       {
1775:         Graphics g2 = g;
1776:         if (!(g instanceof Graphics2D))
1777:           g2 = g.create();
1778:         ui.update(getComponentGraphics(g2), this);
1779:         if (!(g instanceof Graphics2D))
1780:           g2.dispose();
1781:       }
1782:   }
1783: 
1784:   /**
1785:    * A variant of {@link #paintImmediately(Rectangle)} which takes
1786:    * integer parameters.
1787:    *
1788:    * @param x The left x coordinate of the dirty region
1789:    * @param y The top y coordinate of the dirty region
1790:    * @param w The width of the dirty region
1791:    * @param h The height of the dirty region
1792:    */
1793:   public void paintImmediately(int x, int y, int w, int h)
1794:   {
1795:     paintImmediately(new Rectangle(x, y, w, h));
1796:   }
1797: 
1798:   /**
1799:    * Transform the provided dirty rectangle for this component into the
1800:    * appropriate ancestral {@link JRootPane} and call {@link #paint} on
1801:    * that root pane. This method is called from the {@link RepaintManager}
1802:    * and should always be called within the painting thread.
1803:    *
1804:    * <p>This method will acquire a double buffer from the {@link
1805:    * RepaintManager} if the component's {@link #doubleBuffered} property is
1806:    * <code>true</code> and the <code>paint</code> call is the
1807:    * <em>first</em> recursive <code>paint</code> call inside swing.</p>
1808:    *
1809:    * <p>The method will also modify the provided {@link Graphics} context
1810:    * via the {@link #getComponentGraphics} method. If you want to customize
1811:    * the graphics object used for painting, you should override that method
1812:    * rather than <code>paint</code>.</p>
1813:    *
1814:    * @param r The dirty rectangle to paint
1815:    */
1816:   public void paintImmediately(Rectangle r)
1817:   {
1818:     // Try to find a root pane for this component.
1819:     //Component root = findPaintRoot(r);
1820:     Component root = findPaintRoot(r);
1821:     // If no paint root is found, then this component is completely overlapped
1822:     // by another component and we don't need repainting.
1823:     if (root == null)
1824:       return;
1825:     if (root == null || !root.isShowing())
1826:       return;
1827: 
1828:     Rectangle rootClip = SwingUtilities.convertRectangle(this, r, root);
1829:     if (root instanceof JComponent)
1830:       ((JComponent) root).paintImmediately2(rootClip);
1831:     else
1832:       root.repaint(rootClip.x, rootClip.y, rootClip.width, rootClip.height);
1833:   }
1834: 
1835:   /**
1836:    * Performs the actual work of paintImmediatly on the repaint root.
1837:    *
1838:    * @param r the area to be repainted
1839:    */
1840:   void paintImmediately2(Rectangle r)
1841:   {
1842:     RepaintManager rm = RepaintManager.currentManager(this);
1843:     Graphics g = getGraphics();
1844:     g.setClip(r.x, r.y, r.width, r.height);
1845:     if (rm.isDoubleBufferingEnabled() && isDoubleBuffered())
1846:       paintDoubleBuffered(g);
1847:     else
1848:       paintSimple(g);
1849:     g.dispose();
1850:   }
1851: 
1852:   /**
1853:    * Performs double buffered repainting.
1854:    *
1855:    * @param g the graphics context to paint to
1856:    */
1857:   void paintDoubleBuffered(Graphics g)
1858:   {
1859:     
1860:     Rectangle r = g.getClipBounds();
1861:     if (r == null)
1862:       r = new Rectangle(0, 0, getWidth(), getHeight());
1863:     RepaintManager rm = RepaintManager.currentManager(this);
1864: 
1865:     // Paint on the offscreen buffer.
1866:     Image buffer = rm.getOffscreenBuffer(this, getWidth(), getHeight());
1867:     Graphics g2 = buffer.getGraphics();
1868:     g2 = getComponentGraphics(g2);
1869:     g2.setClip(r.x, r.y, r.width, r.height);
1870:     isPaintingDoubleBuffered = true;
1871:     paint(g2);
1872:     isPaintingDoubleBuffered = false;
1873:     g2.dispose();
1874:     
1875:     // Paint the buffer contents on screen.
1876:     g.drawImage(buffer, 0, 0, this);
1877:   }
1878: 
1879:   /**
1880:    * Performs normal painting without double buffering.
1881:    *
1882:    * @param g the graphics context to use
1883:    */
1884:   void paintSimple(Graphics g)
1885:   {
1886:     Graphics g2 = getComponentGraphics(g);
1887:     paint(g2);
1888:   }
1889: 
1890:   /**
1891:    * Return a string representation for this component, for use in
1892:    * debugging.
1893:    *
1894:    * @return A string describing this component.
1895:    */
1896:   protected String paramString()
1897:   {
1898:     StringBuffer sb = new StringBuffer();
1899:     sb.append(super.paramString());
1900:     sb.append(",alignmentX=").append(getAlignmentX());
1901:     sb.append(",alignmentY=").append(getAlignmentY());
1902:     sb.append(",border=");
1903:     if (getBorder() != null)
1904:       sb.append(getBorder());
1905:     sb.append(",maximumSize=");
1906:     if (getMaximumSize() != null)
1907:       sb.append(getMaximumSize());
1908:     sb.append(",minimumSize=");
1909:     if (getMinimumSize() != null)
1910:       sb.append(getMinimumSize());
1911:     sb.append(",preferredSize=");
1912:     if (getPreferredSize() != null)
1913:       sb.append(getPreferredSize());
1914:     return sb.toString();
1915:   }
1916: 
1917:   /**
1918:    * A variant of {@link
1919:    * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which
1920:    * provides <code>null</code> for the command name.   
1921:    */
1922:   public void registerKeyboardAction(ActionListener act,
1923:                                      KeyStroke stroke, 
1924:                                      int cond)
1925:   {
1926:     registerKeyboardAction(act, null, stroke, cond);
1927:   }
1928: 
1929:   /* 
1930:    * There is some charmingly undocumented behavior sun seems to be using
1931:    * to simulate the old register/unregister keyboard binding API. It's not
1932:    * clear to me why this matters, but we shall endeavour to follow suit.
1933:    *
1934:    * Two main thing seem to be happening when you do registerKeyboardAction():
1935:    * 
1936:    *  - no actionMap() entry gets created, just an entry in inputMap()
1937:    *
1938:    *  - the inputMap() entry is a proxy class which invokes the the
1939:    *  binding's actionListener as a target, and which clobbers the command
1940:    *  name sent in the ActionEvent, providing the binding command name
1941:    *  instead.
1942:    *
1943:    * This much you can work out just by asking the input and action maps
1944:    * what they contain after making bindings, and watching the event which
1945:    * gets delivered to the recipient. Beyond that, it seems to be a
1946:    * sun-private solution so I will only immitate it as much as it matters
1947:    * to external observers.
1948:    */
1949:   private static class ActionListenerProxy
1950:     extends AbstractAction
1951:   {
1952:     ActionListener target;
1953:     String bindingCommandName;
1954: 
1955:     public ActionListenerProxy(ActionListener li, 
1956:                                String cmd)
1957:     {
1958:       target = li;
1959:       bindingCommandName = cmd;
1960:     }
1961: 
1962:     public void actionPerformed(ActionEvent e)
1963:     {
1964:       ActionEvent derivedEvent = new ActionEvent(e.getSource(),
1965:                                                  e.getID(),
1966:                                                  bindingCommandName,
1967:                                                  e.getModifiers());
1968:       target.actionPerformed(derivedEvent);
1969:     }
1970:   }
1971: 
1972:   
1973:   /**
1974:    * An obsolete method to register a keyboard action on this component.
1975:    * You should use <code>getInputMap</code> and <code>getActionMap</code>
1976:    * to fetch mapping tables from keystrokes to commands, and commands to
1977:    * actions, respectively, and modify those mappings directly.
1978:    *
1979:    * @param act The action to be registered
1980:    * @param cmd The command to deliver in the delivered {@link
1981:    *     java.awt.event.ActionEvent}
1982:    * @param stroke The keystroke to register on
1983:    * @param cond One of the values {@link #UNDEFINED_CONDITION},
1984:    *     {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or
1985:    *     {@link #WHEN_IN_FOCUSED_WINDOW}, indicating the condition which must
1986:    *     be met for the action to be fired
1987:    *
1988:    * @see #unregisterKeyboardAction
1989:    * @see #getConditionForKeyStroke
1990:    * @see #resetKeyboardActions
1991:    */
1992:   public void registerKeyboardAction(ActionListener act, 
1993:                                      String cmd,
1994:                                      KeyStroke stroke, 
1995:                                      int cond)
1996:   {
1997:     getInputMap(cond).put(stroke, new ActionListenerProxy(act, cmd));
1998:   }
1999: 
2000:   public final void setInputMap(int condition, InputMap map)
2001:   {
2002:     enableEvents(AWTEvent.KEY_EVENT_MASK);
2003:     switch (condition)
2004:       {
2005:       case WHEN_FOCUSED:
2006:         inputMap_whenFocused = map;
2007:         break;
2008: 
2009:       case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2010:         inputMap_whenAncestorOfFocused = map;
2011:         break;
2012: 
2013:       case WHEN_IN_FOCUSED_WINDOW:
2014:         inputMap_whenInFocusedWindow = map;
2015:         break;
2016:         
2017:       case UNDEFINED_CONDITION:
2018:       default:
2019:         throw new IllegalArgumentException();
2020:       }
2021:   }
2022: 
2023:   public final InputMap getInputMap(int condition)
2024:   {
2025:     enableEvents(AWTEvent.KEY_EVENT_MASK);
2026:     switch (condition)
2027:       {
2028:       case WHEN_FOCUSED:
2029:         if (inputMap_whenFocused == null)
2030:           inputMap_whenFocused = new InputMap();
2031:         return inputMap_whenFocused;
2032: 
2033:       case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT:
2034:         if (inputMap_whenAncestorOfFocused == null)
2035:           inputMap_whenAncestorOfFocused = new InputMap();
2036:         return inputMap_whenAncestorOfFocused;
2037: 
2038:       case WHEN_IN_FOCUSED_WINDOW:
2039:         if (inputMap_whenInFocusedWindow == null)
2040:           inputMap_whenInFocusedWindow = new InputMap();
2041:         return inputMap_whenInFocusedWindow;
2042: 
2043:       case UNDEFINED_CONDITION:
2044:       default:
2045:         return null;
2046:       }
2047:   }
2048: 
2049:   public final InputMap getInputMap()
2050:   {
2051:     return getInputMap(WHEN_FOCUSED);
2052:   }
2053: 
2054:   public final ActionMap getActionMap()
2055:   {
2056:     if (actionMap == null)
2057:       actionMap = new ActionMap();
2058:     return actionMap;
2059:   }
2060: 
2061:   public final void setActionMap(ActionMap map)
2062:   {
2063:     actionMap = map;
2064:   }
2065: 
2066:   /**
2067:    * Return the condition that determines whether a registered action
2068:    * occurs in response to the specified keystroke.
2069:    *
2070:    * @param ks The keystroke to return the condition of
2071:    *
2072:    * @return One of the values {@link #UNDEFINED_CONDITION}, {@link
2073:    *     #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or {@link
2074:    *     #WHEN_IN_FOCUSED_WINDOW}
2075:    *
2076:    * @deprecated As of 1.3 KeyStrokes can be registered with multiple
2077:    *     simultaneous conditions.
2078:    *
2079:    * @see #registerKeyboardAction(ActionListener, KeyStroke, int)   
2080:    * @see #unregisterKeyboardAction   
2081:    * @see #resetKeyboardActions
2082:    */
2083:   public int getConditionForKeyStroke(KeyStroke ks)
2084:   {
2085:     if (inputMap_whenFocused != null 
2086:         && inputMap_whenFocused.get(ks) != null)
2087:       return WHEN_FOCUSED;
2088:     else if (inputMap_whenAncestorOfFocused != null 
2089:              && inputMap_whenAncestorOfFocused.get(ks) != null)
2090:       return WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
2091:     else if (inputMap_whenInFocusedWindow != null 
2092:              && inputMap_whenInFocusedWindow.get(ks) != null)
2093:       return WHEN_IN_FOCUSED_WINDOW;
2094:     else
2095:       return UNDEFINED_CONDITION;
2096:   }
2097: 
2098:   /**
2099:    * Get the ActionListener (typically an {@link Action} object) which is
2100:    * associated with a particular keystroke. 
2101:    *
2102:    * @param ks The keystroke to retrieve the action of
2103:    *
2104:    * @return The action associated with the specified keystroke
2105:    *
2106:    * @deprecated Use {@link #getActionMap()}
2107:    */
2108:   public ActionListener getActionForKeyStroke(KeyStroke ks)
2109:   {
2110:     Object cmd = getInputMap().get(ks);
2111:     if (cmd != null)
2112:       {
2113:         if (cmd instanceof ActionListenerProxy)
2114:           return (ActionListenerProxy) cmd;
2115:         else if (cmd instanceof String)
2116:           return getActionMap().get(cmd);
2117:       }
2118:     return null;
2119:   }
2120: 
2121:   /**
2122:    * A hook for subclasses which want to customize event processing.
2123:    */
2124:   protected void processComponentKeyEvent(KeyEvent e)
2125:   {
2126:     // This method does nothing, it is meant to be overridden by subclasses.
2127:   }
2128: 
2129:   /**
2130:    * Override the default key dispatch system from Component to hook into
2131:    * the swing {@link InputMap} / {@link ActionMap} system.
2132:    *
2133:    * See <a
2134:    * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">
2135:    * this report</a> for more details, it's somewhat complex.
2136:    */
2137:   protected void processKeyEvent(KeyEvent e)
2138:   {
2139:     // let the AWT event processing send KeyEvents to registered listeners
2140:     super.processKeyEvent(e);
2141:     processComponentKeyEvent(e);
2142: 
2143:     if (e.isConsumed())
2144:       return;
2145: 
2146:     // Input maps are checked in this order:
2147:     // 1. The focused component's WHEN_FOCUSED map is checked.
2148:     // 2. The focused component's WHEN_ANCESTOR_OF_FOCUSED_COMPONENT map.
2149:     // 3. The WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps of the focused
2150:     //    component's parent, then its parent's parent, and so on.
2151:     //    Note: Input maps for disabled components are skipped.
2152:     // 4. The WHEN_IN_FOCUSED_WINDOW maps of all the enabled components in
2153:     //    the focused window are searched.
2154:     
2155:     if (processKeyBinding(KeyStroke.getKeyStrokeForEvent(e), 
2156:                           e, WHEN_FOCUSED, e.getID() == KeyEvent.KEY_PRESSED))
2157:       // This is step 1 from above comment.
2158:       e.consume();
2159:     else if (processKeyBinding(KeyStroke.getKeyStrokeForEvent(e),
2160:                                e, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
2161:                                e.getID() == KeyEvent.KEY_PRESSED))
2162:       // This is step 2 from above comment.
2163:       e.consume();
2164:     else
2165:       {
2166:         // This is step 3 from above comment.
2167:         Container current = this;
2168:         while ((current = current.getParent()) instanceof JComponent)
2169:           {
2170:             if (((JComponent)current).processKeyBinding
2171:                 (KeyStroke.getKeyStrokeForEvent(e), e, 
2172:                  WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, 
2173:                  e.getID() == KeyEvent.KEY_PRESSED))
2174:               {
2175:                 e.consume();
2176:                 break;
2177:               }
2178:             if (current instanceof Window || current instanceof Applet
2179:                 || current instanceof JInternalFrame)
2180:               break;
2181:           }
2182:         if (e.isConsumed())
2183:           return;
2184:         
2185:         // This is step 4 from above comment.
2186:         // FIXME: Implement.  Note, should use ComponentInputMaps rather
2187:         // than walking the entire containment hierarchy.
2188:       }
2189:   }
2190: 
2191:   protected boolean processKeyBinding(KeyStroke ks,
2192:                                       KeyEvent e,
2193:                                       int condition,
2194:                                       boolean pressed)
2195:   { 
2196:     if (isEnabled())
2197:       {
2198:         Action act = null;
2199:         InputMap map = getInputMap(condition);
2200:         if (map != null)
2201:           {
2202:             Object cmd = map.get(ks);
2203:             if (cmd != null)
2204:               {
2205:                 if (cmd instanceof ActionListenerProxy)
2206:                   act = (Action) cmd;
2207:                 else 
2208:                   act = (Action) getActionMap().get(cmd);
2209:               }
2210:           }
2211:         if (act != null && act.isEnabled())
2212:           return SwingUtilities.notifyAction(act, ks, e, this, e.getModifiers());
2213:       }
2214:     return false;
2215:   }
2216:   
2217:   /**
2218:    * Remove a keyboard action registry.
2219:    *
2220:    * @param aKeyStroke The keystroke to unregister
2221:    *
2222:    * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2223:    * @see #getConditionForKeyStroke
2224:    * @see #resetKeyboardActions
2225:    */
2226:   public void unregisterKeyboardAction(KeyStroke aKeyStroke)
2227:   {
2228:     // FIXME: Must be implemented.
2229:   }
2230: 
2231: 
2232:   /**
2233:    * Reset all keyboard action registries.
2234:    *
2235:    * @see #registerKeyboardAction(ActionListener, KeyStroke, int)
2236:    * @see #unregisterKeyboardAction
2237:    * @see #getConditionForKeyStroke
2238:    */
2239:   public void resetKeyboardActions()
2240:   {
2241:     if (inputMap_whenFocused != null)
2242:       inputMap_whenFocused.clear();
2243:     if (inputMap_whenAncestorOfFocused != null)
2244:       inputMap_whenAncestorOfFocused.clear();
2245:     if (inputMap_whenInFocusedWindow != null)
2246:       inputMap_whenInFocusedWindow.clear();
2247:     if (actionMap != null)
2248:       actionMap.clear();
2249:   }
2250: 
2251:   /**
2252:    * Mark the described region of this component as dirty in the current
2253:    * {@link RepaintManager}. This will queue an asynchronous repaint using
2254:    * the system painting thread in the near future.
2255:    *
2256:    * @param tm ignored
2257:    * @param x coordinate of the region to mark as dirty
2258:    * @param y coordinate of the region to mark as dirty
2259:    * @param width dimension of the region to mark as dirty
2260:    * @param height dimension of the region to mark as dirty
2261:    */
2262:   public void repaint(long tm, int x, int y, int width, int height)
2263:   {
2264:     Rectangle dirty = new Rectangle(x, y, width, height);
2265:     Rectangle vis = getVisibleRect();
2266:     dirty = dirty.intersection(vis);
2267:     RepaintManager.currentManager(this).addDirtyRegion(this, dirty.x, dirty.y,
2268:                                                        dirty.width,
2269:                                                        dirty.height);
2270:   }
2271: 
2272:   /**
2273:    * Mark the described region of this component as dirty in the current
2274:    * {@link RepaintManager}. This will queue an asynchronous repaint using
2275:    * the system painting thread in the near future.
2276:    *
2277:    * @param r The rectangle to mark as dirty
2278:    */
2279:   public void repaint(Rectangle r)
2280:   {
2281:     repaint((long) 0, (int) r.getX(), (int) r.getY(), (int) r.getWidth(),
2282:             (int) r.getHeight());
2283:   }
2284: 
2285:   /**
2286:    * Request focus on the default component of this component's {@link
2287:    * FocusTraversalPolicy}.
2288:    *
2289:    * @return The result of {@link #requestFocus()}
2290:    *
2291:    * @deprecated Use {@link #requestFocus()} on the default component provided
2292:    *     from the {@link FocusTraversalPolicy} instead.
2293:    */
2294:   public boolean requestDefaultFocus()
2295:   {
2296:     return false;
2297:   }
2298: 
2299:   /**
2300:    * Queue a an invalidation and revalidation of this component, using 
2301:    * {@link RepaintManager#addInvalidComponent}.
2302:    */
2303:   public void revalidate()
2304:   {
2305:     if (! EventQueue.isDispatchThread())
2306:       SwingUtilities.invokeLater(new Runnable()
2307:         {
2308:           public void run()
2309:           {
2310:             revalidate();
2311:           }
2312:         });
2313:     else
2314:       {
2315:         invalidate();
2316:         RepaintManager.currentManager(this).addInvalidComponent(this);
2317:       }
2318:   }
2319: 
2320:   /**
2321:    * Calls <code>scrollRectToVisible</code> on the component's parent. 
2322:    * Components which can service this call should override.
2323:    *
2324:    * @param r The rectangle to make visible
2325:    */
2326:   public void scrollRectToVisible(Rectangle r)
2327:   {
2328:     Component p = getParent();
2329:     if (p instanceof JComponent)
2330:       ((JComponent) p).scrollRectToVisible(r);
2331:   }
2332: 
2333:   /**
2334:    * Set the value of the {@link #alignmentX} property.
2335:    *
2336:    * @param a The new value of the property
2337:    */
2338:   public void setAlignmentX(float a)
2339:   {
2340:     alignmentX = a;
2341:   }
2342: 
2343:   /**
2344:    * Set the value of the {@link #alignmentY} property.
2345:    *
2346:    * @param a The new value of the property
2347:    */
2348:   public void setAlignmentY(float a)
2349:   {
2350:     alignmentY = a;
2351:   }
2352: 
2353:   /**
2354:    * Set the value of the {@link #autoscrolls} property.
2355:    *
2356:    * @param a The new value of the property
2357:    */
2358:   public void setAutoscrolls(boolean a)
2359:   {
2360:     autoscrolls = a;
2361:   }
2362: 
2363:   /**
2364:    * Set the value of the {@link #debugGraphicsOptions} property.
2365:    *
2366:    * @param debugOptions The new value of the property
2367:    */
2368:   public void setDebugGraphicsOptions(int debugOptions)
2369:   {
2370:     debugGraphicsOptions = debugOptions;
2371:   }
2372: 
2373:   /**
2374:    * Set the value of the {@link #doubleBuffered} property.
2375:    *
2376:    * @param db The new value of the property
2377:    */
2378:   public void setDoubleBuffered(boolean db)
2379:   {
2380:     doubleBuffered = db;
2381:   }
2382: 
2383:   /**
2384:    * Set the value of the <code>enabled</code> property.
2385:    *
2386:    * @param enable The new value of the property
2387:    */
2388:   public void setEnabled(boolean enable)
2389:   {
2390:     if (enable == isEnabled())
2391:       return;
2392:     super.setEnabled(enable);
2393:     firePropertyChange("enabled", !enable, enable);
2394:     repaint();
2395:   }
2396: 
2397:   /**
2398:    * Set the value of the <code>font</code> property.
2399:    *
2400:    * @param f The new value of the property
2401:    */
2402:   public void setFont(Font f)
2403:   {
2404:     if (f == getFont())
2405:       return;
2406:     super.setFont(f);
2407:     revalidate();
2408:     repaint();
2409:   }
2410: 
2411:   /**
2412:    * Set the value of the <code>background</code> property.
2413:    *
2414:    * @param bg The new value of the property
2415:    */
2416:   public void setBackground(Color bg)
2417:   {
2418:     if (bg == getBackground())
2419:       return;
2420:     super.setBackground(bg);
2421:     repaint();
2422:   }
2423: 
2424:   /**
2425:    * Set the value of the <code>foreground</code> property.
2426:    *
2427:    * @param fg The new value of the property
2428:    */
2429:   public void setForeground(Color fg)
2430:   {
2431:     if (fg == getForeground())
2432:       return;
2433:     super.setForeground(fg);
2434:     repaint();
2435:   }
2436: 
2437:   /**
2438:    * Set the value of the {@link #maximumSize} property.
2439:    *
2440:    * @param max The new value of the property
2441:    */
2442:   public void setMaximumSize(Dimension max)
2443:   {
2444:     Dimension oldMaximumSize = maximumSize;
2445:     maximumSize = max;
2446:     firePropertyChange("maximumSize", oldMaximumSize, maximumSize);
2447:   }
2448: 
2449:   /**
2450:    * Set the value of the {@link #minimumSize} property.
2451:    *
2452:    * @param min The new value of the property
2453:    */
2454:   public void setMinimumSize(Dimension min)
2455:   {
2456:     Dimension oldMinimumSize = minimumSize;
2457:     minimumSize = min;
2458:     firePropertyChange("minimumSize", oldMinimumSize, minimumSize);
2459:   }
2460: 
2461:   /**
2462:    * Set the value of the {@link #preferredSize} property.
2463:    *
2464:    * @param pref The new value of the property
2465:    */
2466:   public void setPreferredSize(Dimension pref)
2467:   {
2468:     Dimension oldPreferredSize = preferredSize;
2469:     preferredSize = pref;
2470:     firePropertyChange("preferredSize", oldPreferredSize, preferredSize);
2471:   }
2472: 
2473:   /**
2474:    * Set the specified component to be the next component in the 
2475:    * focus cycle, overriding the {@link FocusTraversalPolicy} for
2476:    * this component.
2477:    *
2478:    * @param aComponent The component to set as the next focusable
2479:    *
2480:    * @deprecated Use FocusTraversalPolicy instead
2481:    */
2482:   public void setNextFocusableComponent(Component aComponent)
2483:   {
2484:     // TODO: Implement this properly.
2485:   }
2486: 
2487:   /**
2488:    * Set the value of the {@link #requestFocusEnabled} property.
2489:    *
2490:    * @param e The new value of the property
2491:    */
2492:   public void setRequestFocusEnabled(boolean e)
2493:   {
2494:     requestFocusEnabled = e;
2495:   }
2496: 
2497:   /**
2498:    * Get the value of the {@link #transferHandler} property.
2499:    *
2500:    * @return The current value of the property
2501:    *
2502:    * @see #setTransferHandler
2503:    */
2504: 
2505:   public TransferHandler getTransferHandler()
2506:   {
2507:     return transferHandler;
2508:   }
2509: 
2510:   /**
2511:    * Set the value of the {@link #transferHandler} property.
2512:    *
2513:    * @param newHandler The new value of the property
2514:    *
2515:    * @see #getTransferHandler
2516:    */
2517: 
2518:   public void setTransferHandler(TransferHandler newHandler)
2519:   {
2520:     if (transferHandler == newHandler)
2521:       return;
2522: 
2523:     TransferHandler oldHandler = transferHandler;
2524:     transferHandler = newHandler;
2525:     firePropertyChange("transferHandler", oldHandler, newHandler);
2526:   }
2527: 
2528:   /**
2529:    * Set the value of the {@link #opaque} property.
2530:    *
2531:    * @param isOpaque The new value of the property
2532:    *
2533:    * @see ComponentUI#update
2534:    */
2535:   public void setOpaque(boolean isOpaque)
2536:   {
2537:     boolean oldOpaque = opaque;
2538:     opaque = isOpaque;
2539:     firePropertyChange("opaque", oldOpaque, opaque);
2540:   }
2541: 
2542:   /**
2543:    * Set the value of the visible property.
2544:    *
2545:    * If the value is changed, then the AncestorListeners of this component
2546:    * and all its children (recursivly) are notified.
2547:    *
2548:    * @param v The new value of the property
2549:    */
2550:   public void setVisible(boolean v)
2551:   {
2552:     // No need to do anything if the actual value doesn't change.
2553:     if (isVisible() == v)
2554:       return;
2555: 
2556:     super.setVisible(v);
2557: 
2558:     // Notify AncestorListeners.
2559:     if (v == true)
2560:       fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
2561:     else
2562:       fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);
2563: 
2564:     Container parent = getParent();
2565:     if (parent != null)
2566:       parent.repaint(getX(), getY(), getWidth(), getHeight());
2567:     revalidate();
2568:   }
2569: 
2570:   /**
2571:    * Call {@link #paint}. 
2572:    * 
2573:    * @param g The graphics context to paint into
2574:    */
2575:   public void update(Graphics g)
2576:   {
2577:     paint(g);
2578:   }
2579: 
2580:   /**
2581:    * Get the value of the UIClassID property. This property should be a key
2582:    * in the {@link UIDefaults} table managed by {@link UIManager}, the
2583:    * value of which is the name of a class to load for the component's
2584:    * {@link #ui} property.
2585:    *
2586:    * @return A "symbolic" name which will map to a class to use for the
2587:    * component's UI, such as <code>"ComponentUI"</code>
2588:    *
2589:    * @see #setUI
2590:    * @see #updateUI
2591:    */
2592:   public String getUIClassID()
2593:   {
2594:     return "ComponentUI";
2595:   }
2596: 
2597:   /**
2598:    * Install a new UI delegate as the component's {@link #ui} property. In
2599:    * the process, this will call {@link ComponentUI#uninstallUI} on any
2600:    * existing value for the {@link #ui} property, and {@link
2601:    * ComponentUI#installUI} on the new UI delegate.
2602:    *
2603:    * @param newUI The new UI delegate to install
2604:    *
2605:    * @see #updateUI
2606:    * @see #getUIClassID
2607:    */
2608:   protected void setUI(ComponentUI newUI)
2609:   {
2610:     if (ui != null)
2611:       ui.uninstallUI(this);
2612: 
2613:     ComponentUI oldUI = ui;
2614:     ui = newUI;
2615: 
2616:     if (ui != null)
2617:       ui.installUI(this);
2618: 
2619:     firePropertyChange("UI", oldUI, newUI);
2620:     revalidate();
2621:     repaint();
2622:   }
2623: 
2624:   /**
2625:    * This method should be overridden in subclasses. In JComponent, the
2626:    * method does nothing. In subclasses, it should a UI delegate
2627:    * (corresponding to the symbolic name returned from {@link
2628:    * #getUIClassID}) from the {@link UIManager}, and calls {@link #setUI}
2629:    * with the new delegate.
2630:    */
2631:   public void updateUI()
2632:   {
2633:     System.out.println("update UI not overwritten in class: " + this);
2634:   }
2635: 
2636:   public static Locale getDefaultLocale()
2637:   {
2638:     return defaultLocale;
2639:   }
2640:   
2641:   public static void setDefaultLocale(Locale l)
2642:   {
2643:     defaultLocale = l;
2644:   }
2645:   
2646:   /**
2647:    * Returns the currently set input verifier for this component.
2648:    *
2649:    * @return the input verifier, or <code>null</code> if none
2650:    */
2651:   public InputVerifier getInputVerifier()
2652:   {
2653:     return inputVerifier;
2654:   }
2655: 
2656:   /**
2657:    * Sets the input verifier to use by this component.
2658:    *
2659:    * @param verifier the input verifier, or <code>null</code>
2660:    */
2661:   public void setInputVerifier(InputVerifier verifier)
2662:   {
2663:     InputVerifier oldVerifier = inputVerifier;
2664:     inputVerifier = verifier;
2665:     firePropertyChange("inputVerifier", oldVerifier, verifier);
2666:   }
2667: 
2668:   /**
2669:    * @since 1.3
2670:    */
2671:   public boolean getVerifyInputWhenFocusTarget()
2672:   {
2673:     return verifyInputWhenFocusTarget;
2674:   }
2675: 
2676:   /**
2677:    * @since 1.3
2678:    */
2679:   public void setVerifyInputWhenFocusTarget(boolean verifyInputWhenFocusTarget)
2680:   {
2681:     if (this.verifyInputWhenFocusTarget == verifyInputWhenFocusTarget)
2682:       return;
2683: 
2684:     this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget;
2685:     firePropertyChange("verifyInputWhenFocusTarget",
2686:                        ! verifyInputWhenFocusTarget,
2687:                        verifyInputWhenFocusTarget);
2688:   }
2689: 
2690:   /**
2691:    * Requests that this component gets the input focus if the
2692:    * requestFocusEnabled property is set to <code>true</code>.
2693:    * This also means that this component's top-level window becomes
2694:    * the focused window, if that is not already the case.
2695:    *
2696:    * The preconditions that have to be met to become a focus owner is that
2697:    * the component must be displayable, visible and focusable.
2698:    *
2699:    * Note that this signals only a request for becoming focused. There are
2700:    * situations in which it is not possible to get the focus. So developers
2701:    * should not assume that the component has the focus until it receives
2702:    * a {@link java.awt.event.FocusEvent} with a value of
2703:    * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
2704:    *
2705:    * @see Component#requestFocus()
2706:    */
2707:   public void requestFocus()
2708:   {
2709:     if (isRequestFocusEnabled())
2710:       super.requestFocus();
2711:   }
2712: 
2713:   /**
2714:    * This method is overridden to make it public so that it can be used
2715:    * by look and feel implementations.
2716:    *
2717:    * You should not use this method directly. Instead you are strongly
2718:    * encouraged to call {@link #requestFocus()} or 
2719:    * {@link #requestFocusInWindow()} instead.
2720:    *
2721:    * @param temporary if the focus change is temporary
2722:    *
2723:    * @return <code>false</code> if the focus change request will definitly
2724:    *     fail, <code>true</code> if it will likely succeed
2725:    *
2726:    * @see Component#requestFocus(boolean)
2727:    *
2728:    * @since 1.4
2729:    */
2730:   public boolean requestFocus(boolean temporary)
2731:   {
2732:     return super.requestFocus(temporary);
2733:   }
2734: 
2735:   /**
2736:    * Requests that this component gets the input focus if the top level
2737:    * window that contains this component has the focus and the
2738:    * requestFocusEnabled property is set to <code>true</code>.
2739:    *
2740:    * The preconditions that have to be met to become a focus owner is that
2741:    * the component must be displayable, visible and focusable.
2742:    *
2743:    * Note that this signals only a request for becoming focused. There are
2744:    * situations in which it is not possible to get the focus. So developers
2745:    * should not assume that the component has the focus until it receives
2746:    * a {@link java.awt.event.FocusEvent} with a value of
2747:    * {@link java.awt.event.FocusEvent#FOCUS_GAINED}.
2748:    *
2749:    * @return <code>false</code> if the focus change request will definitly
2750:    *     fail, <code>true</code> if it will likely succeed
2751:    *
2752:    * @see Component#requestFocusInWindow()
2753:    */
2754:   public boolean requestFocusInWindow()
2755:   {
2756:     if (isRequestFocusEnabled())
2757:       return super.requestFocusInWindow();
2758:     else
2759:       return false;
2760:   }
2761: 
2762:   /**
2763:    * This method is overridden to make it public so that it can be used
2764:    * by look and feel implementations.
2765:    *
2766:    * You should not use this method directly. Instead you are strongly
2767:    * encouraged to call {@link #requestFocus()} or 
2768:    * {@link #requestFocusInWindow()} instead.
2769:    *
2770:    * @param temporary if the focus change is temporary
2771:    *
2772:    * @return <code>false</code> if the focus change request will definitly
2773:    *     fail, <code>true</code> if it will likely succeed
2774:    *
2775:    * @see Component#requestFocus(boolean)
2776:    *
2777:    * @since 1.4
2778:    */
2779:   public boolean requestFocusInWindow(boolean temporary)
2780:   {
2781:     return super.requestFocusInWindow(temporary);
2782:   }
2783: 
2784:   /**
2785:    * Receives notification if this component is added to a parent component.
2786:    *
2787:    * Notification is sent to all registered AncestorListeners about the
2788:    * new parent.
2789:    *
2790:    * This method sets up ActionListeners for all registered KeyStrokes of
2791:    * this component in the chain of parent components.
2792:    *
2793:    * A PropertyChange event is fired to indicate that the ancestor property
2794:    * has changed.
2795:    *
2796:    * This method is used internally and should not be used in applications.
2797:    */
2798:   public void addNotify()
2799:   {
2800:     super.addNotify();
2801: 
2802:     // let parents inherit the keybord mapping
2803:     InputMap input = getInputMap();
2804:     ActionMap actions = getActionMap();
2805: 
2806:     Container parent = getParent();
2807:     while ((parent != null) && (parent instanceof JComponent))
2808:       {
2809:         JComponent jParent = (JComponent) parent;
2810:         InputMap parentInput = jParent.getInputMap();
2811:         ActionMap parentAction = jParent.getActionMap();
2812: 
2813:         KeyStroke[] ikeys = input.keys();
2814:         for (int i = 0; i < ikeys.length; i++)
2815:           {
2816:             Object o = input.get(ikeys[i]);
2817:             parentInput.put(ikeys[i], o);
2818:           }
2819: 
2820:         Object[] akeys = actions.keys();
2821:         for (int i = 0; i < akeys.length; i++)
2822:           {
2823:             Action a = actions.get(akeys[i]);
2824:             parentAction.put(akeys[i], a);
2825:           }
2826: 
2827:         parent = jParent.getParent();
2828:       }
2829:     
2830:     // Notify AncestorListeners.
2831:     fireAncestorEvent(this, AncestorEvent.ANCESTOR_ADDED);
2832: 
2833:     // fire property change event for 'ancestor'
2834:     firePropertyChange("ancestor", null, parent);
2835:   }
2836: 
2837:   /**
2838:    * Receives notification that this component no longer has a parent.
2839:    *
2840:    * This method sends an AncestorEvent to all registered AncestorListeners,
2841:    * notifying them that the parent is gone.
2842:    *
2843:    * The keybord actions of this component are removed from the parent and
2844:    * its ancestors.
2845:    *
2846:    * A PropertyChangeEvent is fired to indicate that the 'ancestor' property
2847:    * has changed.
2848:    *
2849:    * This method is called before the component is actually removed from
2850:    * its parent, so the parent is still visible through 
2851:    * {@link Component#getParent}.
2852:    */
2853:   public void removeNotify()
2854:   {
2855:     super.removeNotify();
2856: 
2857:     // let parents inherit the keybord mapping
2858:     InputMap input = getInputMap();
2859:     ActionMap actions = getActionMap();
2860: 
2861:     Container parent = getParent();
2862:     while ((parent != null) && (parent instanceof JComponent))
2863:       {
2864:         JComponent jParent = (JComponent) parent;
2865:         InputMap parentInput = jParent.getInputMap();
2866:         ActionMap parentAction = jParent.getActionMap();
2867: 
2868:         KeyStroke[] ikeys = input.allKeys();
2869:         for (int i = 0; i < ikeys.length; i++)
2870:           {
2871:             parentInput.remove(ikeys[i]);
2872:           }
2873: 
2874:         Object[] akeys = actions.allKeys();
2875:         for (int i = 0; i < akeys.length; i++)
2876:           {
2877:             parentAction.remove(akeys[i]);
2878:           }
2879: 
2880:         parent = jParent.getParent();
2881:       }
2882: 
2883:     // Notify ancestor listeners.
2884:     fireAncestorEvent(this, AncestorEvent.ANCESTOR_REMOVED);
2885: 
2886:     // fire property change event for 'ancestor'
2887:     firePropertyChange("ancestor", parent, null);
2888:   }
2889: 
2890:   /**
2891:    * Returns <code>true</code> if the coordinates (x, y) lie within
2892:    * the bounds of this component and <code>false</code> otherwise.
2893:    * x and y are relative to the coordinate space of the component.
2894:    *
2895:    * @param x the X coordinate of the point to check
2896:    * @param y the Y coordinate of the point to check
2897:    *
2898:    * @return <code>true</code> if the specified point lies within the bounds
2899:    *     of this component, <code>false</code> otherwise
2900:    */
2901:   public boolean contains(int x, int y)
2902:   {
2903:     if (ui == null)
2904:       return super.contains(x, y);
2905:     else
2906:       return ui.contains(this, x, y);
2907:   }
2908: 
2909:   /**
2910:    * Disables this component.
2911:    *
2912:    * @deprecated replaced by {@link #setEnabled(boolean)}
2913:    */
2914:   public void disable()
2915:   {
2916:     super.disable();
2917:   }
2918: 
2919:   /**
2920:    * Enables this component.
2921:    *
2922:    * @deprecated replaced by {@link #setEnabled(boolean)}
2923:    */
2924:   public void enable()
2925:   {
2926:     super.enable();
2927:   }
2928: 
2929:   /**
2930:    * Returns the Graphics context for this component. This can be used
2931:    * to draw on a component.
2932:    *
2933:    * @return the Graphics context for this component
2934:    */
2935:   public Graphics getGraphics()
2936:   {
2937:     return super.getGraphics();
2938:   }
2939: 
2940:   /**
2941:    * Returns the X coordinate of the upper left corner of this component.
2942:    * Prefer this method over {@link #getBounds} or {@link #getLocation}
2943:    * because it does not cause any heap allocation.
2944:    *
2945:    * @return the X coordinate of the upper left corner of the component
2946:    */
2947:   public int getX()
2948:   {
2949:     return super.getX();
2950:   }
2951: 
2952:   /**
2953:    * Returns the Y coordinate of the upper left corner of this component.
2954:    * Prefer this method over {@link #getBounds} or {@link #getLocation}
2955:    * because it does not cause any heap allocation.
2956:    *
2957:    * @return the Y coordinate of the upper left corner of the component
2958:    */
2959:   public int getY()
2960:   {
2961:     return super.getY();
2962:   }
2963: 
2964:   /**
2965:    * Returns the height of this component. Prefer this method over
2966:    * {@link #getBounds} or {@link #getSize} because it does not cause
2967:    * any heap allocation.
2968:    *
2969:    * @return the height of the component
2970:    */
2971:   public int getHeight()
2972:   {
2973:     return super.getHeight();
2974:   }
2975: 
2976:   /**
2977:    * Returns the width of this component. Prefer this method over
2978:    * {@link #getBounds} or {@link #getSize} because it does not cause
2979:    * any heap allocation.
2980:    *
2981:    * @return the width of the component
2982:    */
2983:   public int getWidth()
2984:   {
2985:     return super.getWidth();
2986:   }
2987: 
2988:   /**
2989:    * Return all <code>PropertyChangeListener</code> objects registered.
2990:    *
2991:    * @return The set of <code>PropertyChangeListener</code> objects
2992:    */
2993:   public PropertyChangeListener[] getPropertyChangeListeners()
2994:   {
2995:     if (changeSupport == null)
2996:       return new PropertyChangeListener[0];
2997:     else
2998:       return changeSupport.getPropertyChangeListeners();
2999:   }
3000: 
3001:   /**
3002:    * Prints this component to the given Graphics context. A call to this
3003:    * method results in calls to the methods {@link #printComponent},
3004:    * {@link #printBorder} and {@link #printChildren} in this order.
3005:    *
3006:    * Double buffering is temporarily turned off so the painting goes directly
3007:    * to the supplied Graphics context.
3008:    *
3009:    * @param g the Graphics context to print onto
3010:    */
3011:   public void print(Graphics g)
3012:   {
3013:     boolean doubleBufferState = isDoubleBuffered();
3014:     setDoubleBuffered(false);
3015:     printComponent(g);
3016:     printBorder(g);
3017:     printChildren(g);
3018:     setDoubleBuffered(doubleBufferState);
3019:   }
3020: 
3021:   /**
3022:    * Prints this component to the given Graphics context. This invokes
3023:    * {@link #print}.
3024:    *
3025:    * @param g the Graphics context to print onto
3026:    */
3027:   public void printAll(Graphics g)
3028:   {
3029:     print(g);
3030:   }
3031: 
3032:   /**
3033:    * Prints this component to the specified Graphics context. The default
3034:    * behaviour is to invoke {@link #paintComponent}. Override this
3035:    * if you want special behaviour for printing.
3036:    *
3037:    * @param g the Graphics context to print onto
3038:    *
3039:    * @since 1.3
3040:    */
3041:   public void printComponent(Graphics g)
3042:   {
3043:     paintComponent(g);
3044:   }
3045: 
3046:   /**
3047:    * Print this component's children to the specified Graphics context.
3048:    * The default behaviour is to invoke {@link #paintChildren}. Override this
3049:    * if you want special behaviour for printing.
3050:    *
3051:    * @param g the Graphics context to print onto
3052:    *
3053:    * @since 1.3
3054:    */
3055:   public void printChildren(Graphics g)
3056:   {
3057:     paintChildren(g);
3058:   }
3059: 
3060:   /**
3061:    * Print this component's border to the specified Graphics context.
3062:    * The default behaviour is to invoke {@link #paintBorder}. Override this
3063:    * if you want special behaviour for printing.
3064:    *
3065:    * @param g the Graphics context to print onto
3066:    *
3067:    * @since 1.3
3068:    */
3069:   public void printBorder(Graphics g)
3070:   {
3071:     paintBorder(g);
3072:   }
3073: 
3074:   /**
3075:    * Processes mouse motion event, like dragging and moving.
3076:    *
3077:    * @param ev the MouseEvent describing the mouse motion
3078:    */
3079:   protected void processMouseMotionEvent(MouseEvent ev)
3080:   {
3081:     super.processMouseMotionEvent(ev);
3082:   }
3083: 
3084:   /**
3085:    * Moves and resizes the component.
3086:    *
3087:    * @param x the new horizontal location
3088:    * @param y the new vertial location
3089:    * @param w the new width
3090:    * @param h the new height
3091:    */
3092:   public void reshape(int x, int y, int w, int h)
3093:   {
3094:     int oldX = getX();
3095:     int oldY = getY();
3096:     super.reshape(x, y, w, h);
3097:     // Notify AncestorListeners.
3098:     if (oldX != getX() || oldY != getY())
3099:       fireAncestorEvent(this, AncestorEvent.ANCESTOR_MOVED);
3100:   }
3101: 
3102:   /**
3103:    * Fires an AncestorEvent to this component's and all of its child
3104:    * component's AncestorListeners.
3105:    *
3106:    * @param ancestor the component that triggered the event
3107:    * @param id the kind of ancestor event that should be fired
3108:    */
3109:   void fireAncestorEvent(JComponent ancestor, int id)
3110:   {
3111:     // Fire event for registered ancestor listeners of this component.
3112:     AncestorListener[] listeners = getAncestorListeners();
3113:     if (listeners.length > 0)
3114:       {
3115:         AncestorEvent ev = new AncestorEvent(this, id,
3116:                                              ancestor, ancestor.getParent());
3117:         for (int i = 0; i < listeners.length; i++)
3118:           {
3119:             switch (id)
3120:               {
3121:               case AncestorEvent.ANCESTOR_MOVED:
3122:                 listeners[i].ancestorMoved(ev);
3123:                 break;
3124:               case AncestorEvent.ANCESTOR_ADDED:
3125:                 listeners[i].ancestorAdded(ev);
3126:                 break;
3127:               case AncestorEvent.ANCESTOR_REMOVED:
3128:                 listeners[i].ancestorRemoved(ev);
3129:                 break;
3130:               }
3131:           }
3132:       }
3133:     // Dispatch event to all children.
3134:     Component[] children = getComponents();
3135:     for (int i = 0; i < children.length; i++)
3136:       {
3137:         if (!(children[i] instanceof JComponent))
3138:           continue;
3139:         JComponent jc = (JComponent) children[i];
3140:         jc.fireAncestorEvent(ancestor, id);
3141:       }
3142:   }
3143: 
3144:   /**
3145:    * Finds a suitable paint root for painting this component. This method first
3146:    * checks if this component is overlapped using
3147:    * {@link #findOverlapFreeParent(Rectangle)}. The returned paint root is then
3148:    * feeded to {@link #findOpaqueParent(Component)} to find the nearest opaque
3149:    * component for this paint root. If no paint is necessary, then we return
3150:    * <code>null</code>.
3151:    *
3152:    * @param c the clip of this component
3153:    *
3154:    * @return the paint root or <code>null</code> if no painting is necessary
3155:    */
3156:   private Component findPaintRoot(Rectangle c)
3157:   {
3158:     Component p = findOverlapFreeParent(c);
3159:     if (p == null)
3160:       return null;
3161:     Component root = findOpaqueParent(p);
3162:     return root;
3163:   }
3164: 
3165:   /**
3166:    * Scans the containment hierarchy upwards for components that overlap the
3167:    * this component in the specified clip. This method returns
3168:    * <code>this</code>, if no component overlaps this component. It returns
3169:    * <code>null</code> if another component completely covers this component
3170:    * in the specified clip (no repaint necessary). If another component partly
3171:    * overlaps this component in the specified clip, then the parent of this
3172:    * component is returned (this is the component that must be used as repaint
3173:    * root). For efficient lookup, the method
3174:    * {@link #isOptimizedDrawingEnabled()} is used.
3175:    *
3176:    * @param clip the clip of this component
3177:    *
3178:    * @return the paint root, or <code>null</code> if no paint is necessary
3179:    */
3180:   private Component findOverlapFreeParent(Rectangle clip)
3181:   {
3182:     Rectangle currentClip = clip;
3183:     Component found = this;
3184:     Container parent = this; 
3185:     while (parent != null && !(parent instanceof Window))
3186:       {
3187:         Container newParent = parent.getParent();
3188:         if (newParent == null)
3189:           break;
3190:         // If the parent is optimizedDrawingEnabled, then its children are
3191:         // tiled and cannot have an overlapping child. Go directly to next
3192:         // parent.
3193:         if (newParent instanceof JComponent
3194:             && ((JComponent) newParent).isOptimizedDrawingEnabled())
3195:           {
3196:             parent = newParent;
3197:             continue;
3198:           }
3199: 
3200:         // First we must check if the new parent itself somehow clips the
3201:         // target rectangle. This can happen in JViewports.
3202:         Rectangle parRect = new Rectangle(0, 0, newParent.getWidth(),
3203:                                           newParent.getHeight());
3204:         Rectangle target = SwingUtilities.convertRectangle(found,
3205:                                                            currentClip,
3206:                                                            newParent);
3207:         if (target.contains(parRect) || target.intersects(parRect))
3208:           {
3209:             found = newParent;
3210:             currentClip = target;
3211:             parent = newParent;
3212:             continue;
3213:           }
3214: 
3215:         // Otherwise we must check if one of the children of this parent
3216:         // overlaps with the current component.
3217:         Component[] children = newParent.getComponents();
3218:         // This flag is used to skip components that are 'below' the component
3219:         // in question.
3220:         boolean skip = true;
3221:         for (int i = children.length - 1; i >= 0; i--)
3222:           {
3223:             if (children[i] == parent)
3224:               skip = false;
3225:             if (skip)
3226:               continue;
3227:             Component c = children[i];
3228:             Rectangle compBounds = c.getBounds();
3229:             // If the component completely overlaps the clip in question, we
3230:             // don't need to repaint. Return null.
3231:             if (compBounds.contains(target))
3232:               return null;
3233:             if (compBounds.intersects(target))
3234:               {
3235:                 // We found a parent whose children overlap with our current
3236:                 // component. Make this the current component.
3237:                 found = newParent;
3238:                 currentClip = target;
3239:                 break;
3240:               }
3241:           }
3242:         parent = newParent;
3243:       }
3244:     return found;
3245:   }
3246: 
3247:   /**
3248:    * Finds the nearest component to <code>c</code> (upwards in the containment
3249:    * hierarchy), that is opaque. If <code>c</code> itself is opaque,
3250:    * this returns <code>c</code> itself.
3251:    *
3252:    * @param c the start component for the search
3253:    * @return the nearest component to <code>c</code> (upwards in the containment
3254:    *         hierarchy), that is opaque; If <code>c</code> itself is opaque,
3255:    *         this returns <code>c</code> itself
3256:    */
3257:   private Component findOpaqueParent(Component c)
3258:   {
3259:     Component found = c;
3260:     while (true)
3261:       {
3262:         if ((found instanceof JComponent) && ((JComponent) found).isOpaque())
3263:           break;
3264:         else if (!(found instanceof JComponent))
3265:           break;
3266:         Container p = found.getParent();
3267:         if (p == null)
3268:           break;
3269:         else
3270:           found = p;
3271:       }
3272:     return found;
3273:   }
3274: }