Source for javax.swing.JComponent

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