Source for java.awt.Container

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