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