Source for java.awt.Container

   1: /* Container.java -- parent container class in AWT
   2:    Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005  Free Software Foundation
   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 java.awt;
  40: 
  41: import java.awt.event.ComponentListener;
  42: import java.awt.event.ContainerEvent;
  43: import java.awt.event.ContainerListener;
  44: import java.awt.event.KeyEvent;
  45: import java.awt.event.MouseEvent;
  46: import java.awt.peer.ComponentPeer;
  47: import java.awt.peer.ContainerPeer;
  48: import java.awt.peer.LightweightPeer;
  49: import java.beans.PropertyChangeListener;
  50: import java.beans.PropertyChangeSupport;
  51: import java.io.IOException;
  52: import java.io.ObjectInputStream;
  53: import java.io.ObjectOutputStream;
  54: import java.io.PrintStream;
  55: import java.io.PrintWriter;
  56: import java.io.Serializable;
  57: import java.util.Collections;
  58: import java.util.EventListener;
  59: import java.util.HashSet;
  60: import java.util.Iterator;
  61: import java.util.Set;
  62: 
  63: import javax.accessibility.Accessible;
  64: 
  65: import gnu.java.awt.AWTUtilities;
  66: 
  67: /**
  68:  * A generic window toolkit object that acts as a container for other objects.
  69:  * Components are tracked in a list, and new elements are at the end of the
  70:  * list or bottom of the stacking order.
  71:  *
  72:  * @author original author unknown
  73:  * @author Eric Blake (ebb9@email.byu.edu)
  74:  *
  75:  * @since 1.0
  76:  *
  77:  * @status still missing 1.4 support
  78:  */
  79: public class Container extends Component
  80: {
  81:   /**
  82:    * Compatible with JDK 1.0+.
  83:    */
  84:   private static final long serialVersionUID = 4613797578919906343L;
  85: 
  86:   /* Serialized fields from the serialization spec. */
  87:   int ncomponents;
  88:   Component[] component;
  89:   LayoutManager layoutMgr;
  90: 
  91:   LightweightDispatcher dispatcher;
  92: 
  93:   Dimension maxSize;
  94: 
  95:   /**
  96:    * @since 1.4
  97:    */
  98:   boolean focusCycleRoot;
  99: 
 100:   int containerSerializedDataVersion;
 101: 
 102:   /* Anything else is non-serializable, and should be declared "transient". */
 103:   transient ContainerListener containerListener;
 104:   transient PropertyChangeSupport changeSupport; 
 105: 
 106:   /** The focus traversal policy that determines how focus is
 107:       transferred between this Container and its children. */
 108:   private FocusTraversalPolicy focusTraversalPolicy;
 109: 
 110:   /**
 111:    * The focus traversal keys, if not inherited from the parent or default
 112:    * keyboard manager. These sets will contain only AWTKeyStrokes that
 113:    * represent press and release events to use as focus control.
 114:    *
 115:    * @see #getFocusTraversalKeys(int)
 116:    * @see #setFocusTraversalKeys(int, Set)
 117:    * @since 1.4
 118:    */
 119:   transient Set[] focusTraversalKeys;
 120: 
 121:   /**
 122:    * Default constructor for subclasses.
 123:    */
 124:   public Container()
 125:   {
 126:     // Nothing to do here.
 127:   }
 128: 
 129:   /**
 130:    * Returns the number of components in this container.
 131:    *
 132:    * @return The number of components in this container.
 133:    */
 134:   public int getComponentCount()
 135:   {
 136:     return countComponents ();
 137:   }
 138: 
 139:   /**
 140:    * Returns the number of components in this container.
 141:    *
 142:    * @return The number of components in this container.
 143:    *
 144:    * @deprecated use {@link #getComponentCount()} instead
 145:    */
 146:   public int countComponents()
 147:   {
 148:     return ncomponents;
 149:   }
 150: 
 151:   /**
 152:    * Returns the component at the specified index.
 153:    *
 154:    * @param n The index of the component to retrieve.
 155:    *
 156:    * @return The requested component.
 157:    *
 158:    * @throws ArrayIndexOutOfBoundsException If the specified index is invalid
 159:    */
 160:   public Component getComponent(int n)
 161:   {
 162:     synchronized (getTreeLock ())
 163:       {
 164:         if (n < 0 || n >= ncomponents)
 165:           throw new ArrayIndexOutOfBoundsException("no such component");
 166: 
 167:         return component[n];
 168:       }
 169:   }
 170: 
 171:   /**
 172:    * Returns an array of the components in this container.
 173:    *
 174:    * @return The components in this container.
 175:    */
 176:   public Component[] getComponents()
 177:   {
 178:     synchronized (getTreeLock ())
 179:       {
 180:         Component[] result = new Component[ncomponents];
 181: 
 182:         if (ncomponents > 0)
 183:           System.arraycopy(component, 0, result, 0, ncomponents);
 184: 
 185:         return result;
 186:       }
 187:   }
 188: 
 189:   /**
 190:    * Swaps the components at position i and j, in the container.
 191:    */
 192: 
 193:   protected void swapComponents (int i, int j)
 194:   {   
 195:     synchronized (getTreeLock ())
 196:       {
 197:         if (i < 0 
 198:             || i >= component.length
 199:             || j < 0 
 200:             || j >= component.length)
 201:           throw new ArrayIndexOutOfBoundsException ();
 202:         Component tmp = component[i];
 203:         component[i] = component[j];
 204:         component[j] = tmp;
 205:       }
 206:   }
 207: 
 208:   /**
 209:    * Returns the insets for this container, which is the space used for
 210:    * borders, the margin, etc.
 211:    *
 212:    * @return The insets for this container.
 213:    */
 214:   public Insets getInsets()
 215:   {
 216:     return insets ();
 217:   }
 218: 
 219:   /**
 220:    * Returns the insets for this container, which is the space used for
 221:    * borders, the margin, etc.
 222:    *
 223:    * @return The insets for this container.
 224:    * @deprecated use {@link #getInsets()} instead
 225:    */
 226:   public Insets insets()
 227:   {
 228:     if (peer == null)
 229:       return new Insets (0, 0, 0, 0);
 230: 
 231:     return ((ContainerPeer) peer).getInsets ();
 232:   }
 233: 
 234:   /**
 235:    * Adds the specified component to this container at the end of the
 236:    * component list.
 237:    *
 238:    * @param comp The component to add to the container.
 239:    *
 240:    * @return The same component that was added.
 241:    */
 242:   public Component add(Component comp)
 243:   {
 244:     addImpl(comp, null, -1);
 245:     return comp;
 246:   }
 247: 
 248:   /**
 249:    * Adds the specified component to the container at the end of the
 250:    * component list.  This method should not be used. Instead, use
 251:    * <code>add(Component, Object)</code>.
 252:    *
 253:    * @param name The name of the component to be added.
 254:    * @param comp The component to be added.
 255:    *
 256:    * @return The same component that was added.
 257:    *
 258:    * @see #add(Component,Object)
 259:    */
 260:   public Component add(String name, Component comp)
 261:   {
 262:     addImpl(comp, name, -1);
 263:     return comp;
 264:   }
 265: 
 266:   /**
 267:    * Adds the specified component to this container at the specified index
 268:    * in the component list.
 269:    *
 270:    * @param comp The component to be added.
 271:    * @param index The index in the component list to insert this child
 272:    * at, or -1 to add at the end of the list.
 273:    *
 274:    * @return The same component that was added.
 275:    *
 276:    * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
 277:    */
 278:   public Component add(Component comp, int index)
 279:   {
 280:     addImpl(comp, null, index);
 281:     return comp;
 282:   }
 283: 
 284:   /**
 285:    * Adds the specified component to this container at the end of the
 286:    * component list.  The layout manager will use the specified constraints
 287:    * when laying out this component.
 288:    *
 289:    * @param comp The component to be added to this container.
 290:    * @param constraints The layout constraints for this component.
 291:    */
 292:   public void add(Component comp, Object constraints)
 293:   {
 294:     addImpl(comp, constraints, -1);
 295:   }
 296: 
 297:   /**
 298:    * Adds the specified component to this container at the specified index
 299:    * in the component list.  The layout manager will use the specified
 300:    * constraints when layout out this component.
 301:    *
 302:    * @param comp The component to be added.
 303:    * @param constraints The layout constraints for this component.
 304:    * @param index The index in the component list to insert this child
 305:    * at, or -1 to add at the end of the list.
 306:    *
 307:    * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
 308:    */
 309:   public void add(Component comp, Object constraints, int index)
 310:   {
 311:     addImpl(comp, constraints, index);
 312:   }
 313: 
 314:   /**
 315:    * This method is called by all the <code>add()</code> methods to perform
 316:    * the actual adding of the component.  Subclasses who wish to perform
 317:    * their own processing when a component is added should override this
 318:    * method.  Any subclass doing this must call the superclass version of
 319:    * this method in order to ensure proper functioning of the container.
 320:    *
 321:    * @param comp The component to be added.
 322:    * @param constraints The layout constraints for this component, or
 323:    * <code>null</code> if there are no constraints.
 324:    * @param index The index in the component list to insert this child
 325:    * at, or -1 to add at the end of the list.
 326:    *
 327:    * @throws ArrayIndexOutOfBoundsException If the specified index is invalid.
 328:    */
 329:   protected void addImpl(Component comp, Object constraints, int index)
 330:   {
 331:     synchronized (getTreeLock ())
 332:       {
 333:         if (index > ncomponents
 334:             || (index < 0 && index != -1)
 335:             || comp instanceof Window
 336:             || (comp instanceof Container
 337:                 && ((Container) comp).isAncestorOf(this)))
 338:           throw new IllegalArgumentException();
 339: 
 340:         // Reparent component, and make sure component is instantiated if
 341:         // we are.
 342:         if (comp.parent != null)
 343:           comp.parent.remove(comp);
 344:         comp.parent = this;
 345: 
 346:         if (peer != null)
 347:           {
 348:         // Notify the component that it has a new parent.
 349:         comp.addNotify();
 350: 
 351:             if (comp.isLightweight ())
 352:           {
 353:         enableEvents (comp.eventMask);
 354:         if (!isLightweight ())
 355:           enableEvents (AWTEvent.PAINT_EVENT_MASK);
 356:           }
 357:           }
 358: 
 359:         // Invalidate the layout of the added component and its ancestors.
 360:         comp.invalidate();
 361: 
 362:         if (component == null)
 363:           component = new Component[4]; // FIXME, better initial size?
 364: 
 365:         // This isn't the most efficient implementation.  We could do less
 366:         // copying when growing the array.  It probably doesn't matter.
 367:         if (ncomponents >= component.length)
 368:           {
 369:             int nl = component.length * 2;
 370:             Component[] c = new Component[nl];
 371:             System.arraycopy(component, 0, c, 0, ncomponents);
 372:             component = c;
 373:           }
 374:   
 375:         if (index == -1)
 376:           component[ncomponents++] = comp;
 377:         else
 378:           {
 379:             System.arraycopy(component, index, component, index + 1,
 380:                              ncomponents - index);
 381:             component[index] = comp;
 382:             ++ncomponents;
 383:           }
 384: 
 385:         // Notify the layout manager.
 386:         if (layoutMgr != null)
 387:           {
 388:             if (layoutMgr instanceof LayoutManager2)
 389:               {
 390:                 LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
 391:                 lm2.addLayoutComponent(comp, constraints);
 392:               }
 393:             else if (constraints instanceof String)
 394:               layoutMgr.addLayoutComponent((String) constraints, comp);
 395:             else
 396:               layoutMgr.addLayoutComponent(null, comp);
 397:           }
 398: 
 399:         // We previously only sent an event when this container is showing.
 400:         // Also, the event was posted to the event queue. A Mauve test shows
 401:         // that this event is not delivered using the event queue and it is
 402:         // also sent when the container is not showing. 
 403:         ContainerEvent ce = new ContainerEvent(this,
 404:                                                ContainerEvent.COMPONENT_ADDED,
 405:                                                comp);
 406:         ContainerListener[] listeners = getContainerListeners();
 407:         for (int i = 0; i < listeners.length; i++)
 408:           listeners[i].componentAdded(ce);
 409: 
 410:         // Repaint this container.
 411:         repaint(comp.getX(), comp.getY(), comp.getWidth(),
 412:                 comp.getHeight());
 413:       }
 414:   }
 415: 
 416:   /**
 417:    * Removes the component at the specified index from this container.
 418:    *
 419:    * @param index The index of the component to remove.
 420:    */
 421:   public void remove(int index)
 422:   {
 423:     synchronized (getTreeLock ())
 424:       {
 425:         Component r = component[index];
 426: 
 427:         ComponentListener[] list = r.getComponentListeners();
 428:         for (int j = 0; j < list.length; j++)
 429:               r.removeComponentListener(list[j]);
 430:         
 431:         if (r.isShowing())
 432:           r.removeNotify();
 433: 
 434:         System.arraycopy(component, index + 1, component, index,
 435:                          ncomponents - index - 1);
 436:         component[--ncomponents] = null;
 437: 
 438:         invalidate();
 439: 
 440:         if (layoutMgr != null)
 441:           layoutMgr.removeLayoutComponent(r);
 442: 
 443:         r.parent = null;
 444: 
 445:         if (isShowing ())
 446:           {
 447:             // Post event to notify of removing the component.
 448:             ContainerEvent ce = new ContainerEvent(this,
 449:                                                    ContainerEvent.COMPONENT_REMOVED,
 450:                                                    r);
 451:             getToolkit().getSystemEventQueue().postEvent(ce);
 452: 
 453:             // Repaint this container.
 454:             repaint();
 455:           }
 456:       }
 457:   }
 458: 
 459:   /**
 460:    * Removes the specified component from this container.
 461:    *
 462:    * @param comp The component to remove from this container.
 463:    */
 464:   public void remove(Component comp)
 465:   {
 466:     synchronized (getTreeLock ())
 467:       {
 468:         for (int i = 0; i < ncomponents; ++i)
 469:           {
 470:             if (component[i] == comp)
 471:               {
 472:                 remove(i);
 473:                 break;
 474:               }
 475:           }
 476:       }
 477:   }
 478: 
 479:   /**
 480:    * Removes all components from this container.
 481:    */
 482:   public void removeAll()
 483:   {
 484:     synchronized (getTreeLock ())
 485:       {
 486:         while (ncomponents > 0)
 487:           remove(0);
 488:       }
 489:   }
 490: 
 491:   /**
 492:    * Returns the current layout manager for this container.
 493:    *
 494:    * @return The layout manager for this container.
 495:    */
 496:   public LayoutManager getLayout()
 497:   {
 498:     return layoutMgr;
 499:   }
 500: 
 501:   /**
 502:    * Sets the layout manager for this container to the specified layout
 503:    * manager.
 504:    *
 505:    * @param mgr The new layout manager for this container.
 506:    */
 507:   public void setLayout(LayoutManager mgr)
 508:   {
 509:     layoutMgr = mgr;
 510:     invalidate();
 511:   }
 512: 
 513:   /**
 514:    * Layout the components in this container.
 515:    */
 516:   public void doLayout()
 517:   {
 518:     layout ();
 519:   }
 520: 
 521:   /**
 522:    * Layout the components in this container.
 523:    *
 524:    * @deprecated use {@link #doLayout()} instead
 525:    */
 526:   public void layout()
 527:   {
 528:     if (layoutMgr != null)
 529:       layoutMgr.layoutContainer (this);
 530:   }
 531: 
 532:   /**
 533:    * Invalidates this container to indicate that it (and all parent
 534:    * containers) need to be laid out.
 535:    */
 536:   public void invalidate()
 537:   {
 538:     super.invalidate();
 539:     if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
 540:       {
 541:         LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
 542:         lm2.invalidateLayout(this);
 543:       }
 544:   }
 545: 
 546:   /**
 547:    * Re-lays out the components in this container.
 548:    */
 549:   public void validate()
 550:   {
 551:     synchronized (getTreeLock ())
 552:       {
 553:         if (! isValid() && peer != null)
 554:           {
 555:             validateTree();
 556:           }
 557:       }
 558:   }
 559: 
 560:   /**
 561:    * Recursively invalidates the container tree.
 562:    */
 563:   void invalidateTree()
 564:   {
 565:     super.invalidate();  // Clean cached layout state.
 566:     for (int i = 0; i < ncomponents; i++)
 567:       {
 568:         Component comp = component[i];
 569:         comp.invalidate();
 570:         if (comp instanceof Container)
 571:           ((Container) comp).invalidateTree();
 572:       }
 573: 
 574:     if (layoutMgr != null && layoutMgr instanceof LayoutManager2)
 575:       {
 576:         LayoutManager2 lm2 = (LayoutManager2) layoutMgr;
 577:         lm2.invalidateLayout(this);
 578:       }
 579:   }
 580: 
 581:   /**
 582:    * Recursively validates the container tree, recomputing any invalid
 583:    * layouts.
 584:    */
 585:   protected void validateTree()
 586:   {
 587:     if (valid)
 588:       return;
 589: 
 590:     ContainerPeer cPeer = null;
 591:     if (peer != null && ! (peer instanceof LightweightPeer))
 592:       {
 593:         cPeer = (ContainerPeer) peer;
 594:         cPeer.beginValidate();
 595:       }
 596: 
 597:     for (int i = 0; i < ncomponents; ++i)
 598:       {
 599:         Component comp = component[i];
 600: 
 601:         if (comp.getPeer () == null)
 602:           comp.addNotify();
 603:       }
 604: 
 605:     doLayout ();
 606:     for (int i = 0; i < ncomponents; ++i)
 607:       {
 608:         Component comp = component[i];
 609: 
 610:         if (! comp.isValid())
 611:           {
 612:             if (comp instanceof Container)
 613:               {
 614:                 ((Container) comp).validateTree();
 615:               }
 616:             else
 617:               {
 618:                 component[i].validate();
 619:               }
 620:           }
 621:       }
 622: 
 623:     /* children will call invalidate() when they are layed out. It
 624:        is therefore important that valid is not set to true
 625:        until after the children have been layed out. */
 626:     valid = true;
 627: 
 628:     if (cPeer != null)
 629:       cPeer.endValidate();
 630:   }
 631: 
 632:   public void setFont(Font f)
 633:   {
 634:     if( (f != null && (font == null || !font.equals(f)))
 635:         || f == null)
 636:       {
 637:         super.setFont(f);
 638:         // FIXME: Although it might make more sense to invalidate only
 639:         // those children whose font == null, Sun invalidates all children.
 640:         // So we'll do the same.
 641:         invalidateTree();
 642:       }
 643:   }
 644: 
 645:   /**
 646:    * Returns the preferred size of this container.
 647:    *
 648:    * @return The preferred size of this container.
 649:    */
 650:   public Dimension getPreferredSize()
 651:   {
 652:     return preferredSize ();
 653:   }
 654: 
 655:   /**
 656:    * Returns the preferred size of this container.
 657:    *
 658:    * @return The preferred size of this container.
 659:    *
 660:    * @deprecated use {@link #getPreferredSize()} instead
 661:    */
 662:   public Dimension preferredSize()
 663:   {
 664:     synchronized(treeLock)
 665:       {  
 666:         if(valid && prefSize != null)
 667:           return new Dimension(prefSize);
 668:         LayoutManager layout = getLayout();
 669:         if (layout != null)
 670:           {
 671:             Dimension layoutSize = layout.preferredLayoutSize(this);
 672:             if(valid)
 673:               prefSize = layoutSize;
 674:             return new Dimension(layoutSize);
 675:           }
 676:         else
 677:           return super.preferredSize ();
 678:       }
 679:   }
 680: 
 681:   /**
 682:    * Returns the minimum size of this container.
 683:    *
 684:    * @return The minimum size of this container.
 685:    */
 686:   public Dimension getMinimumSize()
 687:   {
 688:     return minimumSize ();
 689:   }
 690: 
 691:   /**
 692:    * Returns the minimum size of this container.
 693:    *
 694:    * @return The minimum size of this container.
 695:    *
 696:    * @deprecated use {@link #getMinimumSize()} instead
 697:    */
 698:   public Dimension minimumSize()
 699:   {
 700:     if(valid && minSize != null)
 701:       return new Dimension(minSize);
 702: 
 703:     LayoutManager layout = getLayout();
 704:     if (layout != null)
 705:       {
 706:         minSize = layout.minimumLayoutSize (this);
 707:         return minSize;
 708:       }    
 709:     else
 710:       return super.minimumSize ();
 711:   }
 712: 
 713:   /**
 714:    * Returns the maximum size of this container.
 715:    *
 716:    * @return The maximum size of this container.
 717:    */
 718:   public Dimension getMaximumSize()
 719:   {
 720:     if (valid && maxSize != null)
 721:       return new Dimension(maxSize);
 722: 
 723:     LayoutManager layout = getLayout();
 724:     if (layout != null && layout instanceof LayoutManager2)
 725:       {
 726:         LayoutManager2 lm2 = (LayoutManager2) layout;
 727:         maxSize = lm2.maximumLayoutSize(this);
 728:         return maxSize;
 729:       }
 730:     else
 731:       return super.getMaximumSize();
 732:   }
 733: 
 734:   /**
 735:    * Returns the preferred alignment along the X axis.  This is a value
 736:    * between 0 and 1 where 0 represents alignment flush left and
 737:    * 1 means alignment flush right, and 0.5 means centered.
 738:    *
 739:    * @return The preferred alignment along the X axis.
 740:    */
 741:   public float getAlignmentX()
 742:   {
 743:     LayoutManager layout = getLayout();
 744:     float alignmentX = 0.0F;
 745:     if (layout != null && layout instanceof LayoutManager2)
 746:       {
 747:         LayoutManager2 lm2 = (LayoutManager2) layout;
 748:         alignmentX = lm2.getLayoutAlignmentX(this);
 749:       }
 750:     else
 751:       alignmentX = super.getAlignmentX();
 752:     return alignmentX;
 753:   }
 754: 
 755:   /**
 756:    * Returns the preferred alignment along the Y axis.  This is a value
 757:    * between 0 and 1 where 0 represents alignment flush top and
 758:    * 1 means alignment flush bottom, and 0.5 means centered.
 759:    *
 760:    * @return The preferred alignment along the Y axis.
 761:    */
 762:   public float getAlignmentY()
 763:   {
 764:     LayoutManager layout = getLayout();
 765:     float alignmentY = 0.0F;
 766:     if (layout != null && layout instanceof LayoutManager2)
 767:       {
 768:         LayoutManager2 lm2 = (LayoutManager2) layout;
 769:         alignmentY = lm2.getLayoutAlignmentY(this);
 770:       }
 771:     else
 772:       alignmentY = super.getAlignmentY();
 773:     return alignmentY;
 774:   }
 775: 
 776:   /**
 777:    * Paints this container.  The implementation of this method in this
 778:    * class forwards to any lightweight components in this container.  If
 779:    * this method is subclassed, this method should still be invoked as
 780:    * a superclass method so that lightweight components are properly
 781:    * drawn.
 782:    *
 783:    * @param g The graphics context for this paint job.
 784:    */
 785:   public void paint(Graphics g)
 786:   {
 787:     if (!isShowing())
 788:       return;
 789: 
 790:     // Visit heavyweights as well, in case they were
 791:     // erased when we cleared the background for this container.
 792:     visitChildren(g, GfxPaintVisitor.INSTANCE, false);
 793:   }
 794: 
 795:   /**
 796:    * Updates this container.  The implementation of this method in this
 797:    * class forwards to any lightweight components in this container.  If
 798:    * this method is subclassed, this method should still be invoked as
 799:    * a superclass method so that lightweight components are properly
 800:    * drawn.
 801:    *
 802:    * @param g The graphics context for this update.
 803:    *
 804:    * @specnote The specification suggests that this method forwards the
 805:    *           update() call to all its lightweight children. Tests show
 806:    *           that this is not done either in the JDK. The exact behaviour
 807:    *           seems to be that the background is cleared in heavyweight
 808:    *           Containers, and all other containers
 809:    *           directly call paint(), causing the (lightweight) children to
 810:    *           be painted.
 811:    */
 812:   public void update(Graphics g)
 813:   {
 814:     // It seems that the JDK clears the background of containers like Panel
 815:     // and Window (within this method) but not of 'plain' Containers or
 816:     // JComponents. This could
 817:     // lead to the assumption that it only clears heavyweight containers.
 818:     // However that is not quite true. In a test with a custom Container
 819:     // that overrides isLightweight() to return false, the background is
 820:     // also not cleared. So we do a check on !(peer instanceof LightweightPeer)
 821:     // instead.
 822:     ComponentPeer p = peer;
 823:     if (p != null && !(p instanceof LightweightPeer))
 824:       g.clearRect(0, 0, getWidth(), getHeight());
 825: 
 826:     paint(g);
 827:   }
 828: 
 829:   /**
 830:    * Prints this container.  The implementation of this method in this
 831:    * class forwards to any lightweight components in this container.  If
 832:    * this method is subclassed, this method should still be invoked as
 833:    * a superclass method so that lightweight components are properly
 834:    * drawn.
 835:    *
 836:    * @param g The graphics context for this print job.
 837:    */
 838:   public void print(Graphics g)
 839:   {
 840:     super.print(g);
 841:     visitChildren(g, GfxPrintVisitor.INSTANCE, true);
 842:   }
 843: 
 844:   /**
 845:    * Paints all of the components in this container.
 846:    *
 847:    * @param g The graphics context for this paint job.
 848:    */
 849:   public void paintComponents(Graphics g)
 850:   {
 851:     paint(g);
 852:     visitChildren(g, GfxPaintAllVisitor.INSTANCE, true);
 853:   }
 854: 
 855:   /**
 856:    * Prints all of the components in this container.
 857:    *
 858:    * @param g The graphics context for this print job.
 859:    */
 860:   public void printComponents(Graphics g)
 861:   {
 862:     super.paint(g);
 863:     visitChildren(g, GfxPrintAllVisitor.INSTANCE, true);
 864:   }
 865: 
 866:   /**
 867:    * Adds the specified container listener to this object's list of
 868:    * container listeners.
 869:    *
 870:    * @param listener The listener to add.
 871:    */
 872:   public synchronized void addContainerListener(ContainerListener listener)
 873:   {
 874:     containerListener = AWTEventMulticaster.add(containerListener, listener);
 875:   }
 876: 
 877:   /**
 878:    * Removes the specified container listener from this object's list of
 879:    * container listeners.
 880:    *
 881:    * @param listener The listener to remove.
 882:    */
 883:   public synchronized void removeContainerListener(ContainerListener listener)
 884:   {
 885:     containerListener = AWTEventMulticaster.remove(containerListener, listener);
 886:   }
 887: 
 888:   /**
 889:    * @since 1.4
 890:    */
 891:   public synchronized ContainerListener[] getContainerListeners()
 892:   {
 893:     return (ContainerListener[])
 894:       AWTEventMulticaster.getListeners(containerListener,
 895:                                        ContainerListener.class);
 896:   }
 897: 
 898:   /**
 899:    * Returns an array of all the objects currently registered as FooListeners
 900:    * upon this Container. FooListeners are registered using the addFooListener
 901:    * method.
 902:    *
 903:    * @exception ClassCastException If listenerType doesn't specify a class or
 904:    * interface that implements @see java.util.EventListener.
 905:    *
 906:    * @since 1.3
 907:    */
 908:   public EventListener[] getListeners(Class listenerType)
 909:   {
 910:     if (listenerType == ContainerListener.class)
 911:       return getContainerListeners();
 912:     return super.getListeners(listenerType);
 913:   }
 914: 
 915:   /**
 916:    * Processes the specified event.  This method calls
 917:    * <code>processContainerEvent()</code> if this method is a
 918:    * <code>ContainerEvent</code>, otherwise it calls the superclass
 919:    * method.
 920:    *
 921:    * @param e The event to be processed.
 922:    */
 923:   protected void processEvent(AWTEvent e)
 924:   {
 925:     if (e instanceof ContainerEvent)
 926:       processContainerEvent((ContainerEvent) e);
 927:     else
 928:       super.processEvent(e);
 929:   }
 930: 
 931:   /**
 932:    * Called when a container event occurs if container events are enabled.
 933:    * This method calls any registered listeners.
 934:    *
 935:    * @param e The event that occurred.
 936:    */
 937:   protected void processContainerEvent(ContainerEvent e)
 938:   {
 939:     if (containerListener == null)
 940:       return;
 941:     switch (e.id)
 942:       {
 943:       case ContainerEvent.COMPONENT_ADDED:
 944:         containerListener.componentAdded(e);
 945:         break;
 946: 
 947:       case ContainerEvent.COMPONENT_REMOVED:
 948:         containerListener.componentRemoved(e);
 949:         break;
 950:       }
 951:   }
 952: 
 953:   /**
 954:    * AWT 1.0 event processor.
 955:    *
 956:    * @param e The event that occurred.
 957:    *
 958:    * @deprecated use {@link #dispatchEvent(AWTEvent)} instead
 959:    */
 960:   public void deliverEvent(Event e)
 961:   {
 962:     if (!handleEvent (e))
 963:       {
 964:         synchronized (getTreeLock ())
 965:           {
 966:             Component parent = getParent ();
 967: 
 968:             if (parent != null)
 969:               parent.deliverEvent (e);
 970:           }
 971:       }
 972:   }
 973: 
 974:   /**
 975:    * Returns the component located at the specified point.  This is done
 976:    * by checking whether or not a child component claims to contain this
 977:    * point.  The first child component that does is returned.  If no
 978:    * child component claims the point, the container itself is returned,
 979:    * unless the point does not exist within this container, in which
 980:    * case <code>null</code> is returned.
 981:    *
 982:    * @param x The X coordinate of the point.
 983:    * @param y The Y coordinate of the point.
 984:    *
 985:    * @return The component containing the specified point, or
 986:    * <code>null</code> if there is no such point.
 987:    */
 988:   public Component getComponentAt(int x, int y)
 989:   {
 990:     return locate (x, y);
 991:   }
 992: 
 993:   /**
 994:    * Returns the component located at the specified point.  This is done
 995:    * by checking whether or not a child component claims to contain this
 996:    * point.  The first child component that does is returned.  If no
 997:    * child component claims the point, the container itself is returned,
 998:    * unless the point does not exist within this container, in which
 999:    * case <code>null</code> is returned.
1000:    *
1001:    * @param x The x position of the point to return the component at.
1002:    * @param y The y position of the point to return the component at.
1003:    *
1004:    * @return The component containing the specified point, or <code>null</code>
1005:    * if there is no such point.
1006:    *
1007:    * @deprecated use {@link #getComponentAt(int, int)} instead
1008:    */
1009:   public Component locate(int x, int y)
1010:   {
1011:     synchronized (getTreeLock ())
1012:       {
1013:         if (!contains (x, y))
1014:           return null;
1015:         for (int i = 0; i < ncomponents; ++i)
1016:           {
1017:             // Ignore invisible children...
1018:             if (!component[i].isVisible ())
1019:               continue;
1020: 
1021:             int x2 = x - component[i].x;
1022:             int y2 = y - component[i].y;
1023:             if (component[i].contains (x2, y2))
1024:               return component[i];
1025:           }
1026:         return this;
1027:       }
1028:   }
1029: 
1030:   /**
1031:    * Returns the component located at the specified point.  This is done
1032:    * by checking whether or not a child component claims to contain this
1033:    * point.  The first child component that does is returned.  If no
1034:    * child component claims the point, the container itself is returned,
1035:    * unless the point does not exist within this container, in which
1036:    * case <code>null</code> is returned.
1037:    *
1038:    * @param p The point to return the component at.
1039:    * @return The component containing the specified point, or <code>null</code>
1040:    * if there is no such point.
1041:    */
1042:   public Component getComponentAt(Point p)
1043:   {
1044:     return getComponentAt (p.x, p.y);
1045:   }
1046: 
1047:   public Component findComponentAt(int x, int y)
1048:   {
1049:     synchronized (getTreeLock ())
1050:       {
1051:         if (! contains(x, y))
1052:           return null;
1053: 
1054:         for (int i = 0; i < ncomponents; ++i)
1055:           {
1056:             // Ignore invisible children...
1057:             if (!component[i].isVisible())
1058:               continue;
1059: 
1060:             int x2 = x - component[i].x;
1061:             int y2 = y - component[i].y;
1062:             // We don't do the contains() check right away because
1063:             // findComponentAt would redundantly do it first thing.
1064:             if (component[i] instanceof Container)
1065:               {
1066:                 Container k = (Container) component[i];
1067:                 Component r = k.findComponentAt(x2, y2);
1068:                 if (r != null)
1069:                   return r;
1070:               }
1071:             else if (component[i].contains(x2, y2))
1072:               return component[i];
1073:           }
1074: 
1075:         return this;
1076:       }
1077:   }
1078:   
1079:   /**
1080:    * Finds the visible child component that contains the specified position.
1081:    * The top-most child is returned in the case where there is overlap.
1082:    * If the top-most child is transparent and has no MouseListeners attached,
1083:    * we discard it and return the next top-most component containing the
1084:    * specified position.
1085:    * @param x the x coordinate
1086:    * @param y the y coordinate
1087:    * @return null if the <code>this</code> does not contain the position,
1088:    * otherwise the top-most component (out of this container itself and 
1089:    * its descendants) meeting the criteria above.
1090:    */
1091:   Component findComponentForMouseEventAt(int x, int y)
1092:   {
1093:     synchronized (getTreeLock())
1094:       {
1095:         if (!contains(x, y))
1096:           return null;
1097: 
1098:         for (int i = 0; i < ncomponents; ++i)
1099:           {
1100:             // Ignore invisible children...
1101:             if (!component[i].isVisible())
1102:               continue;
1103: 
1104:             int x2 = x - component[i].x;
1105:             int y2 = y - component[i].y;
1106:             // We don't do the contains() check right away because
1107:             // findComponentAt would redundantly do it first thing.
1108:             if (component[i] instanceof Container)
1109:               {
1110:                 Container k = (Container) component[i];
1111:                 Component r = k.findComponentForMouseEventAt(x2, y2);
1112:                 if (r != null)
1113:                   return r;
1114:               }
1115:             else if (component[i].contains(x2, y2))
1116:               return component[i];
1117:           }
1118: 
1119:         //don't return transparent components with no MouseListeners
1120:         if (this.getMouseListeners().length == 0)
1121:           return null;
1122:         return this;
1123:       }
1124:   }
1125: 
1126:   public Component findComponentAt(Point p)
1127:   {
1128:     return findComponentAt(p.x, p.y);
1129:   }
1130: 
1131:   /**
1132:    * Called when this container is added to another container to inform it
1133:    * to create its peer.  Peers for any child components will also be
1134:    * created.
1135:    */
1136:   public void addNotify()
1137:   {
1138:     super.addNotify();
1139:     addNotifyContainerChildren();
1140:   }
1141: 
1142:   /**
1143:    * Called when this container is removed from its parent container to
1144:    * inform it to destroy its peer.  This causes the peers of all child
1145:    * component to be destroyed as well.
1146:    */
1147:   public void removeNotify()
1148:   {
1149:     synchronized (getTreeLock ())
1150:       {
1151:         for (int i = 0; i < ncomponents; ++i)
1152:           component[i].removeNotify();
1153:         super.removeNotify();
1154:       }
1155:   }
1156: 
1157:   /**
1158:    * Tests whether or not the specified component is contained within
1159:    * this components subtree.
1160:    *
1161:    * @param comp The component to test.
1162:    *
1163:    * @return <code>true</code> if this container is an ancestor of the
1164:    * specified component, <code>false</code> otherwise.
1165:    */
1166:   public boolean isAncestorOf(Component comp)
1167:   {
1168:     synchronized (getTreeLock ())
1169:       {
1170:         while (true)
1171:           {
1172:             if (comp == null)
1173:               return false;
1174:             if (comp == this)
1175:               return true;
1176:             comp = comp.getParent();
1177:           }
1178:       }
1179:   }
1180: 
1181:   /**
1182:    * Returns a string representing the state of this container for
1183:    * debugging purposes.
1184:    *
1185:    * @return A string representing the state of this container.
1186:    */
1187:   protected String paramString()
1188:   {
1189:     if (layoutMgr == null)
1190:       return super.paramString();
1191: 
1192:     StringBuffer sb = new StringBuffer();
1193:     sb.append(super.paramString());
1194:     sb.append(",layout=");
1195:     sb.append(layoutMgr.getClass().getName());
1196:     return sb.toString();
1197:   }
1198: 
1199:   /**
1200:    * Writes a listing of this container to the specified stream starting
1201:    * at the specified indentation point.
1202:    *
1203:    * @param out The <code>PrintStream</code> to write to.
1204:    * @param indent The indentation point.
1205:    */
1206:   public void list(PrintStream out, int indent)
1207:   {
1208:     synchronized (getTreeLock ())
1209:       {
1210:         super.list(out, indent);
1211:         for (int i = 0; i < ncomponents; ++i)
1212:           component[i].list(out, indent + 2);
1213:       }
1214:   }
1215: 
1216:   /**
1217:    * Writes a listing of this container to the specified stream starting
1218:    * at the specified indentation point.
1219:    *
1220:    * @param out The <code>PrintWriter</code> to write to.
1221:    * @param indent The indentation point.
1222:    */
1223:   public void list(PrintWriter out, int indent)
1224:   {
1225:     synchronized (getTreeLock ())
1226:       {
1227:         super.list(out, indent);
1228:         for (int i = 0; i < ncomponents; ++i)
1229:           component[i].list(out, indent + 2);
1230:       }
1231:   }
1232: 
1233:   /**
1234:    * Sets the focus traversal keys for a given traversal operation for this
1235:    * Container.
1236:    *
1237:    * @exception IllegalArgumentException If id is not one of
1238:    * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1239:    * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1240:    * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
1241:    * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS,
1242:    * or if keystrokes contains null, or if any Object in keystrokes is not an
1243:    * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, or if any
1244:    * keystroke already maps to another focus traversal operation for this
1245:    * Container.
1246:    *
1247:    * @since 1.4
1248:    */
1249:   public void setFocusTraversalKeys(int id, Set keystrokes)
1250:   {
1251:     if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1252:         id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1253:         id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1254:         id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1255:       throw new IllegalArgumentException ();
1256: 
1257:     if (keystrokes == null)
1258:       {
1259:         Container parent = getParent ();
1260: 
1261:         while (parent != null)
1262:           {
1263:             if (parent.areFocusTraversalKeysSet (id))
1264:               {
1265:                 keystrokes = parent.getFocusTraversalKeys (id);
1266:                 break;
1267:               }
1268:             parent = parent.getParent ();
1269:           }
1270: 
1271:         if (keystrokes == null)
1272:           keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
1273:             getDefaultFocusTraversalKeys (id);
1274:       }
1275: 
1276:     Set sa;
1277:     Set sb;
1278:     Set sc;
1279:     String name;
1280:     switch (id)
1281:       {
1282:       case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
1283:         sa = getFocusTraversalKeys
1284:           (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1285:         sb = getFocusTraversalKeys
1286:           (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1287:         sc = getFocusTraversalKeys
1288:           (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1289:         name = "forwardFocusTraversalKeys";
1290:         break;
1291:       case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
1292:         sa = getFocusTraversalKeys
1293:           (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1294:         sb = getFocusTraversalKeys
1295:           (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1296:         sc = getFocusTraversalKeys
1297:           (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1298:         name = "backwardFocusTraversalKeys";
1299:         break;
1300:       case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
1301:         sa = getFocusTraversalKeys
1302:           (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1303:         sb = getFocusTraversalKeys
1304:           (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1305:         sc = getFocusTraversalKeys
1306:           (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1307:         name = "upCycleFocusTraversalKeys";
1308:         break;
1309:       case KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS:
1310:         sa = getFocusTraversalKeys
1311:           (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1312:         sb = getFocusTraversalKeys
1313:           (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1314:         sc = getFocusTraversalKeys
1315:           (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1316:         name = "downCycleFocusTraversalKeys";
1317:         break;
1318:       default:
1319:         throw new IllegalArgumentException ();
1320:       }
1321: 
1322:     int i = keystrokes.size ();
1323:     Iterator iter = keystrokes.iterator ();
1324: 
1325:     while (--i >= 0)
1326:       {
1327:         Object o = iter.next ();
1328:         if (!(o instanceof AWTKeyStroke)
1329:             || sa.contains (o) || sb.contains (o) || sc.contains (o)
1330:             || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
1331:           throw new IllegalArgumentException ();
1332:       }
1333: 
1334:     if (focusTraversalKeys == null)
1335:       focusTraversalKeys = new Set[4];
1336: 
1337:     keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
1338:     firePropertyChange (name, focusTraversalKeys[id], keystrokes);
1339: 
1340:     focusTraversalKeys[id] = keystrokes;
1341:   }
1342:   
1343:   /**
1344:    * Returns the Set of focus traversal keys for a given traversal operation for
1345:    * this Container.
1346:    *
1347:    * @exception IllegalArgumentException If id is not one of
1348:    * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1349:    * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1350:    * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
1351:    * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS.
1352:    *
1353:    * @since 1.4
1354:    */
1355:   public Set getFocusTraversalKeys (int id)
1356:   {
1357:     if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1358:         id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1359:         id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1360:         id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1361:       throw new IllegalArgumentException ();
1362: 
1363:     Set s = null;
1364: 
1365:     if (focusTraversalKeys != null)
1366:       s = focusTraversalKeys[id];
1367: 
1368:     if (s == null && parent != null)
1369:       s = parent.getFocusTraversalKeys (id);
1370: 
1371:     return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
1372:                         .getDefaultFocusTraversalKeys(id)) : s;
1373:   }
1374: 
1375:   /**
1376:    * Returns whether the Set of focus traversal keys for the given focus
1377:    * traversal operation has been explicitly defined for this Container.
1378:    * If this method returns false, this Container is inheriting the Set from
1379:    * an ancestor, or from the current KeyboardFocusManager.
1380:    *
1381:    * @exception IllegalArgumentException If id is not one of
1382:    * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1383:    * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1384:    * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
1385:    * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS.
1386:    *
1387:    * @since 1.4
1388:    */
1389:   public boolean areFocusTraversalKeysSet (int id)
1390:   {
1391:     if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1392:         id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1393:         id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1394:         id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1395:       throw new IllegalArgumentException ();
1396: 
1397:     return focusTraversalKeys != null && focusTraversalKeys[id] != null;
1398:   }
1399: 
1400:   /**
1401:    * Check whether the given Container is the focus cycle root of this
1402:    * Container's focus traversal cycle.  If this Container is a focus
1403:    * cycle root itself, then it will be in two different focus cycles
1404:    * -- it's own, and that of its ancestor focus cycle root's.  In
1405:    * that case, if <code>c</code> is either of those containers, this
1406:    * method will return true.
1407:    *
1408:    * @param c the candidate Container
1409:    *
1410:    * @return true if c is the focus cycle root of the focus traversal
1411:    * cycle to which this Container belongs, false otherwise
1412:    *
1413:    * @since 1.4
1414:    */
1415:   public boolean isFocusCycleRoot (Container c)
1416:   {
1417:     if (this == c
1418:         && isFocusCycleRoot ())
1419:       return true;
1420: 
1421:     Container ancestor = getFocusCycleRootAncestor ();
1422: 
1423:     if (c == ancestor)
1424:       return true;
1425: 
1426:     return false;
1427:   }
1428: 
1429:   /**
1430:    * If this Container is a focus cycle root, set the focus traversal
1431:    * policy that determines the focus traversal order for its
1432:    * children.  If non-null, this policy will be inherited by all
1433:    * inferior focus cycle roots.  If <code>policy</code> is null, this
1434:    * Container will inherit its policy from the closest ancestor focus
1435:    * cycle root that's had its policy set.
1436:    *
1437:    * @param policy the new focus traversal policy for this Container or null
1438:    *
1439:    * @since 1.4
1440:    */
1441:   public void setFocusTraversalPolicy (FocusTraversalPolicy policy)
1442:   {
1443:     focusTraversalPolicy = policy;
1444:   }
1445: 
1446:   /**
1447:    * Return the focus traversal policy that determines the focus
1448:    * traversal order for this Container's children.  This method
1449:    * returns null if this Container is not a focus cycle root.  If the
1450:    * focus traversal policy has not been set explicitly, then this
1451:    * method will return an ancestor focus cycle root's policy instead.
1452:    *
1453:    * @return this Container's focus traversal policy or null
1454:    *
1455:    * @since 1.4
1456:    */
1457:   public FocusTraversalPolicy getFocusTraversalPolicy ()
1458:   {
1459:     if (!isFocusCycleRoot ())
1460:       return null;
1461: 
1462:     if (focusTraversalPolicy == null)
1463:       {
1464:         Container ancestor = getFocusCycleRootAncestor ();
1465: 
1466:     if (ancestor != this)
1467:       return ancestor.getFocusTraversalPolicy ();
1468:     else
1469:       {
1470:         KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
1471: 
1472:         return manager.getDefaultFocusTraversalPolicy ();
1473:       }
1474:       }
1475:     else
1476:       return focusTraversalPolicy;
1477:   }
1478: 
1479:   /**
1480:    * Check whether this Container's focus traversal policy has been
1481:    * explicitly set.  If it has not, then this Container will inherit
1482:    * its focus traversal policy from one of its ancestor focus cycle
1483:    * roots.
1484:    *
1485:    * @return true if focus traversal policy is set, false otherwise
1486:   */
1487:   public boolean isFocusTraversalPolicySet ()
1488:   {
1489:     return focusTraversalPolicy == null;
1490:   }
1491: 
1492:   /**
1493:    * Set whether or not this Container is the root of a focus
1494:    * traversal cycle.  This Container's focus traversal policy
1495:    * determines the order of focus traversal.  Some policies prevent
1496:    * the focus from being transferred between two traversal cycles
1497:    * until an up or down traversal operation is performed.  In that
1498:    * case, normal traversal (not up or down) is limited to this
1499:    * Container and all of this Container's descendents that are not
1500:    * descendents of inferior focus cycle roots.  In the default case
1501:    * however, ContainerOrderFocusTraversalPolicy is in effect, and it
1502:    * supports implicit down-cycle traversal operations.
1503:    *
1504:    * @param focusCycleRoot true if this is a focus cycle root, false otherwise
1505:    *
1506:    * @since 1.4
1507:    */
1508:   public void setFocusCycleRoot (boolean focusCycleRoot)
1509:   {
1510:     this.focusCycleRoot = focusCycleRoot;
1511:   }
1512: 
1513:   /**
1514:    * Check whether this Container is a focus cycle root.
1515:    *
1516:    * @return true if this is a focus cycle root, false otherwise
1517:    *
1518:    * @since 1.4
1519:    */
1520:   public boolean isFocusCycleRoot ()
1521:   {
1522:     return focusCycleRoot;
1523:   }
1524: 
1525:   /**
1526:    * Transfer focus down one focus traversal cycle.  If this Container
1527:    * is a focus cycle root, then its default component becomes the
1528:    * focus owner, and this Container becomes the current focus cycle
1529:    * root.  No traversal will occur if this Container is not a focus
1530:    * cycle root.
1531:    *
1532:    * @since 1.4
1533:    */
1534:   public void transferFocusDownCycle ()
1535:   {
1536:     KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
1537: 
1538:     manager.downFocusCycle (this);
1539:   }
1540: 
1541:   /**
1542:    * Sets the ComponentOrientation property of this container and all components
1543:    * contained within it.
1544:    *
1545:    * @exception NullPointerException If orientation is null
1546:    *
1547:    * @since 1.4
1548:    */
1549:   public void applyComponentOrientation (ComponentOrientation orientation)
1550:   {
1551:     if (orientation == null)
1552:       throw new NullPointerException ();
1553:   }
1554:   
1555:   public void addPropertyChangeListener (PropertyChangeListener listener)
1556:   {
1557:     if (listener == null)
1558:       return;
1559: 
1560:     if (changeSupport == null)
1561:       changeSupport = new PropertyChangeSupport (this);
1562: 
1563:     changeSupport.addPropertyChangeListener (listener);
1564:   }
1565:   
1566:   public void addPropertyChangeListener (String name,
1567:                                          PropertyChangeListener listener)
1568:   {
1569:     if (listener == null)
1570:       return;
1571:     
1572:     if (changeSupport == null)
1573:       changeSupport = new PropertyChangeSupport (this);
1574: 
1575:     changeSupport.addPropertyChangeListener (name, listener);
1576:   }
1577: 
1578:   // Hidden helper methods.
1579: 
1580:   /**
1581:    * Perform a graphics operation on the children of this container.
1582:    * For each applicable child, the visitChild() method will be called
1583:    * to perform the graphics operation.
1584:    *
1585:    * @param gfx The graphics object that will be used to derive new
1586:    * graphics objects for the children.
1587:    *
1588:    * @param visitor Object encapsulating the graphics operation that
1589:    * should be performed.
1590:    *
1591:    * @param lightweightOnly If true, only lightweight components will
1592:    * be visited.
1593:    */
1594:   private void visitChildren(Graphics gfx, GfxVisitor visitor,
1595:                              boolean lightweightOnly)
1596:   {
1597:     synchronized (getTreeLock ())
1598:       {
1599:         for (int i = ncomponents - 1; i >= 0; --i)
1600:           {
1601:             Component comp = component[i];
1602:             boolean applicable = comp.isVisible()
1603:               && (comp.isLightweight() || !lightweightOnly);
1604: 
1605:             if (applicable)
1606:               visitChild(gfx, visitor, comp);
1607:       }
1608:       }
1609:   }
1610: 
1611:   /**
1612:    * Perform a graphics operation on a child. A translated and clipped
1613:    * graphics object will be created, and the visit() method of the
1614:    * visitor will be called to perform the operation.
1615:    *
1616:    * @param gfx The graphics object that will be used to derive new
1617:    * graphics objects for the child.
1618:    *
1619:    * @param visitor Object encapsulating the graphics operation that
1620:    * should be performed.
1621:    *
1622:    * @param comp The child component that should be visited.
1623:    */
1624:   private void visitChild(Graphics gfx, GfxVisitor visitor,
1625:                           Component comp)
1626:   {
1627:     Rectangle bounds = comp.getBounds();
1628:     Rectangle oldClip = gfx.getClipBounds();
1629:     if (oldClip == null)
1630:       oldClip = bounds;
1631: 
1632:     Rectangle clip = oldClip.intersection(bounds);
1633: 
1634:     if (clip.isEmpty()) return;
1635: 
1636:     boolean clipped = false;
1637:     boolean translated = false;
1638:     try
1639:       {
1640:         gfx.setClip(clip.x, clip.y, clip.width, clip.height);
1641:         clipped = true;
1642:         gfx.translate(bounds.x, bounds.y);
1643:         translated = true;
1644:         visitor.visit(comp, gfx);
1645:       }
1646:     finally
1647:       {
1648:         if (translated)
1649:           gfx.translate (-bounds.x, -bounds.y);
1650:         if (clipped)
1651:           gfx.setClip (oldClip.x, oldClip.y, oldClip.width, oldClip.height);
1652:       }
1653:   }
1654: 
1655:   void dispatchEventImpl(AWTEvent e)
1656:   {
1657:     // Give lightweight dispatcher a chance to handle it.
1658:     if (dispatcher != null && dispatcher.handleEvent (e))
1659:       return;
1660: 
1661:     if ((e.id <= ContainerEvent.CONTAINER_LAST
1662:              && e.id >= ContainerEvent.CONTAINER_FIRST)
1663:         && (containerListener != null
1664:             || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0))
1665:       processEvent(e);
1666:     else
1667:       super.dispatchEventImpl(e);
1668:   }
1669: 
1670:   /**
1671:    * Tests if this container has an interest in the given event id.
1672:    *
1673:    * @param eventId The event id to check.
1674:    *
1675:    * @return <code>true</code> if a listener for the event id exists or
1676:    *         if the eventMask is set for the event id.
1677:    *
1678:    * @see java.awt.Component#eventTypeEnabled(int)
1679:    */
1680:   boolean eventTypeEnabled(int eventId)
1681:   {
1682:     if(eventId <= ContainerEvent.CONTAINER_LAST 
1683:        && eventId >= ContainerEvent.CONTAINER_FIRST)
1684:       return containerListener != null
1685:         || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0;
1686:       else 
1687:         return super.eventTypeEnabled(eventId);
1688:   }
1689: 
1690:   // This is used to implement Component.transferFocus.
1691:   Component findNextFocusComponent(Component child)
1692:   {
1693:     synchronized (getTreeLock ())
1694:       {
1695:         int start, end;
1696:         if (child != null)
1697:           {
1698:             for (start = 0; start < ncomponents; ++start)
1699:               {
1700:                 if (component[start] == child)
1701:                   break;
1702:               }
1703:             end = start;
1704:             // This special case lets us be sure to terminate.
1705:             if (end == 0)
1706:               end = ncomponents;
1707:             ++start;
1708:           }
1709:         else
1710:           {
1711:             start = 0;
1712:             end = ncomponents;
1713:           }
1714: 
1715:         for (int j = start; j != end; ++j)
1716:           {
1717:             if (j >= ncomponents)
1718:               {
1719:                 // The JCL says that we should wrap here.  However, that
1720:                 // seems wrong.  To me it seems that focus order should be
1721:                 // global within in given window.  So instead if we reach
1722:                 // the end we try to look in our parent, if we have one.
1723:                 if (parent != null)
1724:                   return parent.findNextFocusComponent(this);
1725:                 j -= ncomponents;
1726:               }
1727:             if (component[j] instanceof Container)
1728:               {
1729:                 Component c = component[j];
1730:                 c = c.findNextFocusComponent(null);
1731:                 if (c != null)
1732:                   return c;
1733:               }
1734:             else if (component[j].isFocusTraversable())
1735:               return component[j];
1736:           }
1737: 
1738:         return null;
1739:       }
1740:   }
1741: 
1742:   private void addNotifyContainerChildren()
1743:   {
1744:     synchronized (getTreeLock ())
1745:       {
1746:         for (int i = ncomponents;  --i >= 0; )
1747:           {
1748:             component[i].addNotify();
1749:             if (component[i].isLightweight ())
1750:           {
1751: 
1752:                 // If we're not lightweight, and we just got a lightweight
1753:                 // child, we need a lightweight dispatcher to feed it events.
1754:                 if (!this.isLightweight() && dispatcher == null) 
1755:                   dispatcher = new LightweightDispatcher (this);
1756: 
1757:                 if (dispatcher != null)
1758:                   dispatcher.enableEvents(component[i].eventMask);
1759: 
1760:         enableEvents(component[i].eventMask);
1761:         if (peer != null && !isLightweight ())
1762:           enableEvents (AWTEvent.PAINT_EVENT_MASK);
1763:           }
1764:           }
1765:       }
1766:   }
1767: 
1768:   /**
1769:    * Deserialize this Container:
1770:    * <ol>
1771:    * <li>Read from the stream the default serializable fields.</li>
1772:    * <li>Read a list of serializable ContainerListeners as optional
1773:    * data.  If the list is null, no listeners will be registered.</li>
1774:    * <li>Read this Container's FocusTraversalPolicy as optional data.
1775:    * If this is null, then this Container will use a
1776:    * DefaultFocusTraversalPolicy.</li>
1777:    * </ol>
1778:    *
1779:    * @param s the stream to read from
1780:    * @throws ClassNotFoundException if deserialization fails
1781:    * @throws IOException if the stream fails
1782:    */
1783:   private void readObject (ObjectInputStream s)
1784:     throws ClassNotFoundException, IOException
1785:   {
1786:     s.defaultReadObject ();
1787:     String key = (String) s.readObject ();
1788:     while (key != null)
1789:       {
1790:         Object object = s.readObject ();
1791:         if ("containerL".equals (key))
1792:           addContainerListener((ContainerListener) object);
1793:         // FIXME: under what key is the focus traversal policy stored?
1794:         else if ("focusTraversalPolicy".equals (key))
1795:           setFocusTraversalPolicy ((FocusTraversalPolicy) object);
1796: 
1797:         key = (String) s.readObject();
1798:       }
1799:   }
1800: 
1801:   /**
1802:    * Serialize this Container:
1803:    * <ol>
1804:    * <li>Write to the stream the default serializable fields.</li>
1805:    * <li>Write the list of serializable ContainerListeners as optional
1806:    * data.</li>
1807:    * <li>Write this Container's FocusTraversalPolicy as optional data.</li>
1808:    * </ol>
1809:    *
1810:    * @param s the stream to write to
1811:    * @throws IOException if the stream fails
1812:    */
1813:   private void writeObject (ObjectOutputStream s) throws IOException
1814:   {
1815:     s.defaultWriteObject ();
1816:     AWTEventMulticaster.save (s, "containerL", containerListener);
1817:     if (focusTraversalPolicy instanceof Serializable)
1818:       s.writeObject (focusTraversalPolicy);
1819:     else
1820:       s.writeObject (null);
1821:   }
1822: 
1823:   // Nested classes.
1824: 
1825:   /* The following classes are used in concert with the
1826:      visitChildren() method to implement all the graphics operations
1827:      that requires traversal of the containment hierarchy. */
1828: 
1829:   abstract static class GfxVisitor
1830:   {
1831:     public abstract void visit(Component c, Graphics gfx);
1832:   }
1833: 
1834:   static class GfxPaintVisitor extends GfxVisitor
1835:   {
1836:     public static final GfxVisitor INSTANCE = new GfxPaintVisitor();
1837:     
1838:     public void visit(Component c, Graphics gfx)
1839:     {
1840:       c.paint(gfx);
1841:     }
1842:   }
1843: 
1844:   static class GfxPrintVisitor extends GfxVisitor
1845:   {
1846:     public static final GfxVisitor INSTANCE = new GfxPrintVisitor();
1847:     
1848:     public void visit(Component c, Graphics gfx)
1849:     {
1850:       c.print(gfx);
1851:     }
1852:   }
1853: 
1854:   static class GfxPaintAllVisitor extends GfxVisitor
1855:   {
1856:     public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor();
1857: 
1858:     public void visit(Component c, Graphics gfx)
1859:     {
1860:       c.paintAll(gfx);
1861:     }
1862:   }
1863: 
1864:   static class GfxPrintAllVisitor extends GfxVisitor
1865:   {
1866:     public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor();
1867: 
1868:     public void visit(Component c, Graphics gfx)
1869:     {
1870:       c.printAll(gfx);
1871:     }
1872:   }
1873: 
1874:   /**
1875:    * This class provides accessibility support for subclasses of container.
1876:    *
1877:    * @author Eric Blake (ebb9@email.byu.edu)
1878:    *
1879:    * @since 1.3
1880:    */
1881:   protected class AccessibleAWTContainer extends AccessibleAWTComponent
1882:   {
1883:     /**
1884:      * Compatible with JDK 1.4+.
1885:      */
1886:     private static final long serialVersionUID = 5081320404842566097L;
1887: 
1888:     /**
1889:      * The handler to fire PropertyChange when children are added or removed.
1890:      *
1891:      * @serial the handler for property changes
1892:      */
1893:     protected ContainerListener accessibleContainerHandler
1894:       = new AccessibleContainerHandler();
1895: 
1896:     /**
1897:      * The default constructor.
1898:      */
1899:     protected AccessibleAWTContainer()
1900:     {
1901:       Container.this.addContainerListener(accessibleContainerHandler);
1902:     }
1903: 
1904:     /**
1905:      * Return the number of accessible children of the containing accessible
1906:      * object (at most the total number of its children).
1907:      *
1908:      * @return the number of accessible children
1909:      */
1910:     public int getAccessibleChildrenCount()
1911:     {
1912:       synchronized (getTreeLock ())
1913:         {
1914:           int count = 0;
1915:           int i = component == null ? 0 : component.length;
1916:           while (--i >= 0)
1917:             if (component[i] instanceof Accessible)
1918:               count++;
1919:           return count;
1920:         }
1921:     }
1922: 
1923:     /**
1924:      * Return the nth accessible child of the containing accessible object.
1925:      *
1926:      * @param i the child to grab, zero-based
1927:      * @return the accessible child, or null
1928:      */
1929:     public Accessible getAccessibleChild(int i)
1930:     {
1931:       synchronized (getTreeLock ())
1932:         {
1933:           if (component == null)
1934:             return null;
1935:           int index = -1;
1936:           while (i >= 0 && ++index < component.length)
1937:             if (component[index] instanceof Accessible)
1938:               i--;
1939:           if (i < 0)
1940:             return (Accessible) component[index];
1941:           return null;
1942:         }
1943:     }
1944: 
1945:     /**
1946:      * Return the accessible child located at point (in the parent's
1947:      * coordinates), if one exists.
1948:      *
1949:      * @param p the point to look at
1950:      *
1951:      * @return an accessible object at that point, or null
1952:      *
1953:      * @throws NullPointerException if p is null
1954:      */
1955:     public Accessible getAccessibleAt(Point p)
1956:     {
1957:       Component c = getComponentAt(p.x, p.y);
1958:       return c != Container.this && c instanceof Accessible ? (Accessible) c
1959:         : null;
1960:     }
1961: 
1962:     /**
1963:      * This class fires a <code>PropertyChange</code> listener, if registered,
1964:      * when children are added or removed from the enclosing accessible object.
1965:      *
1966:      * @author Eric Blake (ebb9@email.byu.edu)
1967:      *
1968:      * @since 1.3
1969:      */
1970:     protected class AccessibleContainerHandler implements ContainerListener
1971:     {
1972:       /**
1973:        * Default constructor.
1974:        */
1975:       protected AccessibleContainerHandler()
1976:       {
1977:         // Nothing to do here.
1978:       }
1979: 
1980:       /**
1981:        * Fired when a component is added; forwards to the PropertyChange
1982:        * listener.
1983:        *
1984:        * @param e the container event for adding
1985:        */
1986:       public void componentAdded(ContainerEvent e)
1987:       {
1988:         AccessibleAWTContainer.this.firePropertyChange
1989:           (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild());
1990:       }
1991: 
1992:       /**
1993:        * Fired when a component is removed; forwards to the PropertyChange
1994:        * listener.
1995:        *
1996:        * @param e the container event for removing
1997:        */
1998:       public void componentRemoved(ContainerEvent e)
1999:       {
2000:         AccessibleAWTContainer.this.firePropertyChange
2001:           (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null);
2002:       }
2003:     } // class AccessibleContainerHandler
2004:   } // class AccessibleAWTContainer
2005: } // class Container
2006: 
2007: /**
2008:  * There is a helper class implied from stack traces called
2009:  * LightweightDispatcher, but since it is not part of the public API,
2010:  * rather than mimic it exactly we write something which does "roughly
2011:  * the same thing".
2012:  */
2013: class LightweightDispatcher implements Serializable
2014: {
2015:   private static final long serialVersionUID = 5184291520170872969L;
2016:   private Container nativeContainer;
2017:   private Cursor nativeCursor;
2018:   private long eventMask;
2019:   
2020:   private transient Component pressedComponent;
2021:   private transient Component lastComponentEntered;
2022:   private transient int pressCount;
2023:   
2024:   LightweightDispatcher(Container c)
2025:   {
2026:     nativeContainer = c;
2027:   }
2028: 
2029:   void enableEvents(long l)
2030:   {
2031:     eventMask |= l;
2032:   }
2033: 
2034:   /**
2035:    * Returns the deepest visible descendent of parent that contains the 
2036:    * specified location and that is not transparent and MouseListener-less.
2037:    * @param parent the root component to begin the search
2038:    * @param x the x coordinate
2039:    * @param y the y coordinate
2040:    * @return null if <code>parent</code> doesn't contain the location, 
2041:    * parent if parent is not a container or has no child that contains the
2042:    * location, otherwise the appropriate component from the conditions
2043:    * above.
2044:    */
2045:   Component getDeepestComponentForMouseEventAt(Component parent, int x, int y)
2046:   {
2047:     if (parent == null || (! parent.contains(x, y)))
2048:       return null;
2049: 
2050:     if (! (parent instanceof Container))
2051:       return parent;
2052: 
2053:     Container c = (Container) parent;
2054:     return c.findComponentForMouseEventAt(x, y);
2055:   }
2056:   
2057:   Component acquireComponentForMouseEvent(MouseEvent me)
2058:   {
2059:     int x = me.getX ();
2060:     int y = me.getY ();
2061: 
2062:     Component mouseEventTarget = null;
2063:     // Find the candidate which should receive this event.
2064:     Component parent = nativeContainer;
2065:     Component candidate = null;
2066:     Point p = me.getPoint();
2067:     while (candidate == null && parent != null)
2068:       {
2069:         candidate = getDeepestComponentForMouseEventAt(parent, p.x, p.y);
2070:         if (candidate == null || (candidate.eventMask & me.getID()) == 0)
2071:           {
2072:             candidate = null;
2073:             p = AWTUtilities.convertPoint(parent, p.x, p.y, parent.parent);
2074:             parent = parent.parent;
2075:           }
2076:       }
2077: 
2078:     // If the only candidate we found was the native container itself,
2079:     // don't dispatch any event at all.  We only care about the lightweight
2080:     // children here.
2081:     if (candidate == nativeContainer)
2082:       candidate = null;
2083: 
2084:     // If our candidate is new, inform the old target we're leaving.
2085:     if (lastComponentEntered != null
2086:         && lastComponentEntered.isShowing()
2087:         && lastComponentEntered != candidate)
2088:       {
2089:         // Old candidate could have been removed from 
2090:         // the nativeContainer so we check first.
2091:         if (AWTUtilities.isDescendingFrom(lastComponentEntered,
2092:                                           nativeContainer))
2093:           {
2094:             Point tp = AWTUtilities.convertPoint(nativeContainer, 
2095:                                                  x, y, lastComponentEntered);
2096:             MouseEvent exited = new MouseEvent (lastComponentEntered, 
2097:                                                 MouseEvent.MOUSE_EXITED,
2098:                                                 me.getWhen (), 
2099:                                                 me.getModifiersEx (), 
2100:                                                 tp.x, tp.y,
2101:                                                 me.getClickCount (),
2102:                                                 me.isPopupTrigger (),
2103:                                                 me.getButton ());
2104:             lastComponentEntered.dispatchEvent (exited); 
2105:           }
2106:         lastComponentEntered = null;
2107:       }
2108: 
2109:     // If we have a candidate, maybe enter it.
2110:     if (candidate != null)
2111:       {
2112:         mouseEventTarget = candidate;
2113:         if (candidate.isLightweight() 
2114:             && candidate.isShowing()
2115:             && candidate != nativeContainer
2116:             && candidate != lastComponentEntered)
2117:       {
2118:             lastComponentEntered = mouseEventTarget;
2119:             Point cp = AWTUtilities.convertPoint(nativeContainer, 
2120:                                                  x, y, lastComponentEntered);
2121:             MouseEvent entered = new MouseEvent (lastComponentEntered, 
2122:                                                  MouseEvent.MOUSE_ENTERED,
2123:                                                  me.getWhen (), 
2124:                                                  me.getModifiersEx (), 
2125:                                                  cp.x, cp.y,
2126:                                                  me.getClickCount (),
2127:                                                  me.isPopupTrigger (),
2128:                                                  me.getButton ());
2129:             lastComponentEntered.dispatchEvent (entered);
2130:           }
2131:       }
2132: 
2133:     // Check which buttons where pressed except the last button that
2134:     // changed state.
2135:     int modifiers = me.getModifiersEx() & (MouseEvent.BUTTON1_DOWN_MASK
2136:                                            | MouseEvent.BUTTON2_DOWN_MASK
2137:                                            | MouseEvent.BUTTON3_DOWN_MASK);
2138:     switch(me.getButton())
2139:       {
2140:       case MouseEvent.BUTTON1:
2141:         modifiers &= ~MouseEvent.BUTTON1_DOWN_MASK;
2142:         break;
2143:       case MouseEvent.BUTTON2:
2144:         modifiers &= ~MouseEvent.BUTTON2_DOWN_MASK;
2145:         break;
2146:       case MouseEvent.BUTTON3:
2147:         modifiers &= ~MouseEvent.BUTTON3_DOWN_MASK;
2148:         break;
2149:       }
2150: 
2151:     if (me.getID() == MouseEvent.MOUSE_PRESSED && modifiers > 0
2152:         || me.getID() == MouseEvent.MOUSE_DRAGGED)
2153:       {
2154:         // If any of the following events occur while a button is held down,
2155:         // they should be dispatched to the same component to which the
2156:         // original MOUSE_PRESSED event was dispatched:
2157:         //   - MOUSE_PRESSED: another button pressed while the first is held
2158:         //     down
2159:         //   - MOUSE_DRAGGED
2160:         if (AWTUtilities.isDescendingFrom(pressedComponent, nativeContainer))
2161:           mouseEventTarget = pressedComponent;
2162:       }
2163:     else if (me.getID() == MouseEvent.MOUSE_CLICKED)
2164:       {
2165:         // Don't dispatch CLICKED events whose target is not the same as the
2166:         // target for the original PRESSED event.
2167:         if (candidate != pressedComponent)
2168:           {
2169:             mouseEventTarget = null;
2170:             pressCount = 0;
2171:           }
2172:         else if (pressCount == 0)
2173:           pressedComponent = null;
2174:       }
2175:     return mouseEventTarget;
2176:   }
2177: 
2178:   boolean handleEvent(AWTEvent e)
2179:   {
2180:     if (e instanceof MouseEvent)
2181:       {
2182:         MouseEvent me = (MouseEvent) e;
2183: 
2184:         // Make the LightWeightDispatcher reentrant. This is necessary when
2185:         // a lightweight component does its own modal event queue.
2186:         Component mouseEventTarget = acquireComponentForMouseEvent(me);
2187: 
2188:         // Avoid dispatching ENTERED and EXITED events twice.
2189:         if (mouseEventTarget != null
2190:             && mouseEventTarget.isShowing()
2191:             && e.getID() != MouseEvent.MOUSE_ENTERED
2192:             && e.getID() != MouseEvent.MOUSE_EXITED)
2193:           {
2194:             switch (e.getID())
2195:               {
2196:               case MouseEvent.MOUSE_PRESSED:
2197:                 if (pressCount++ == 0)
2198:                   pressedComponent = mouseEventTarget;
2199:                 break;
2200:               case MouseEvent.MOUSE_RELEASED:
2201:                 // Clear our memory of the original PRESSED event, only if
2202:                 // we're not expecting a CLICKED event after this. If
2203:                 // there is a CLICKED event after this, it will do clean up.
2204:                 if (--pressCount == 0
2205:                     && mouseEventTarget != pressedComponent)
2206:                   {
2207:                     pressedComponent = null;
2208:                     pressCount = 0;
2209:                   }
2210:                 break;
2211:               }
2212: 
2213:             MouseEvent newEvt =
2214:               AWTUtilities.convertMouseEvent(nativeContainer, me,
2215:                                              mouseEventTarget);
2216:             mouseEventTarget.dispatchEvent(newEvt);
2217: 
2218:             if (newEvt.isConsumed())
2219:               e.consume();
2220:           }
2221:       }
2222: 
2223:     return e.isConsumed();
2224:   }
2225: }