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 component located at the specified point.  This is done
1102:    * by checking whether or not a child component claims to contain this
1103:    * point.  The first child component that does is returned.  If no
1104:    * child component claims the point, the container itself is returned,
1105:    * unless the point does not exist within this container, in which
1106:    * case <code>null</code> is returned.
1107:    * 
1108:    * When components overlap, the first component is returned. The component
1109:    * that is closest to (x, y), containing that location, is returned. 
1110:    * Heavyweight components take precedence of lightweight components.
1111:    * 
1112:    * This function does not ignore invisible components. If there is an invisible
1113:    * component at (x,y), it will be returned.
1114:    * 
1115:    * @param x The x position of the point to return the component at.
1116:    * @param y The y position of the point to return the component at.
1117:    *
1118:    * @return The component containing the specified point, or <code>null</code>
1119:    * if there is no such point.
1120:    *
1121:    * @deprecated use {@link #getComponentAt(int, int)} instead
1122:    */
1123:   public Component locate(int x, int y)
1124:   {
1125:     synchronized (getTreeLock ())
1126:       {
1127:         if (!contains (x, y))
1128:           return null;
1129:         
1130:         // First find the component closest to (x,y) that is a heavyweight.
1131:         for (int i = 0; i < ncomponents; ++i)
1132:           {
1133:             Component comp = component[i];
1134:             int x2 = x - comp.x;
1135:             int y2 = y - comp.y;
1136:             if (comp.contains (x2, y2) && !comp.isLightweight())
1137:               return comp;
1138:           }
1139:         
1140:         // if a heavyweight component is not found, look for a lightweight
1141:         // closest to (x,y).
1142:         for (int i = 0; i < ncomponents; ++i)
1143:           {
1144:             Component comp = component[i];
1145:             int x2 = x - comp.x;
1146:             int y2 = y - comp.y;
1147:             if (comp.contains (x2, y2) && comp.isLightweight())
1148:               return comp;
1149:           }
1150:         
1151:         return this;
1152:       }
1153:   }
1154: 
1155:   /**
1156:    * Returns the component located at the specified point.  This is done
1157:    * by checking whether or not a child component claims to contain this
1158:    * point.  The first child component that does is returned.  If no
1159:    * child component claims the point, the container itself is returned,
1160:    * unless the point does not exist within this container, in which
1161:    * case <code>null</code> is returned.
1162:    *
1163:    * The top-most child component is returned in the case where components overlap.
1164:    * This is determined by finding the component closest to (x,y) and contains 
1165:    * that location. Heavyweight components take precedence of lightweight components.
1166:    * 
1167:    * This function does not ignore invisible components. If there is an invisible
1168:    * component at (x,y), it will be returned.
1169:    * 
1170:    * @param p The point to return the component at.
1171:    * @return The component containing the specified point, or <code>null</code>
1172:    * if there is no such point.
1173:    */
1174:   public Component getComponentAt(Point p)
1175:   {
1176:     return getComponentAt (p.x, p.y);
1177:   }
1178: 
1179:   /**
1180:    * Locates the visible child component that contains the specified position. 
1181:    * The top-most child component is returned in the case where there is overlap
1182:    * in the components. If the containing child component is a Container,
1183:    * this method will continue searching for the deepest nested child 
1184:    * component. Components which are not visible are ignored during the search.
1185:    * 
1186:    * findComponentAt differs from getComponentAt, because it recursively 
1187:    * searches a Container's children.
1188:    * 
1189:    * @param x - x coordinate
1190:    * @param y - y coordinate
1191:    * @return null if the component does not contain the position. 
1192:    * If there is no child component at the requested point and the point is 
1193:    * within the bounds of the container the container itself is returned.
1194:    */
1195:   public Component findComponentAt(int x, int y)
1196:   {
1197:     synchronized (getTreeLock ())
1198:       {
1199:         if (! contains(x, y))
1200:           return null;
1201: 
1202:         for (int i = 0; i < ncomponents; ++i)
1203:           {
1204:             // Ignore invisible children...
1205:             if (!component[i].isVisible())
1206:               continue;
1207: 
1208:             int x2 = x - component[i].x;
1209:             int y2 = y - component[i].y;
1210:             // We don't do the contains() check right away because
1211:             // findComponentAt would redundantly do it first thing.
1212:             if (component[i] instanceof Container)
1213:               {
1214:                 Container k = (Container) component[i];
1215:                 Component r = k.findComponentAt(x2, y2);
1216:                 if (r != null)
1217:                   return r;
1218:               }
1219:             else if (component[i].contains(x2, y2))
1220:               return component[i];
1221:           }
1222: 
1223:         return this;
1224:       }
1225:   }
1226:   
1227:   /**
1228:    * Locates the visible child component that contains the specified position. 
1229:    * The top-most child component is returned in the case where there is overlap
1230:    * in the components. If the containing child component is a Container,
1231:    * this method will continue searching for the deepest nested child 
1232:    * component. Components which are not visible are ignored during the search.
1233:    * 
1234:    * findComponentAt differs from getComponentAt, because it recursively 
1235:    * searches a Container's children.
1236:    * 
1237:    * @param p - the component's location
1238:    * @return null if the component does not contain the position. 
1239:    * If there is no child component at the requested point and the point is 
1240:    * within the bounds of the container the container itself is returned.
1241:    */
1242:   public Component findComponentAt(Point p)
1243:   {
1244:     return findComponentAt(p.x, p.y);
1245:   }
1246: 
1247:   /**
1248:    * Called when this container is added to another container to inform it
1249:    * to create its peer.  Peers for any child components will also be
1250:    * created.
1251:    */
1252:   public void addNotify()
1253:   {
1254:     synchronized (getTreeLock())
1255:       {
1256:         super.addNotify();
1257:         addNotifyContainerChildren();
1258:       }
1259:   }
1260: 
1261:   /**
1262:    * Called when this container is removed from its parent container to
1263:    * inform it to destroy its peer.  This causes the peers of all child
1264:    * component to be destroyed as well.
1265:    */
1266:   public void removeNotify()
1267:   {
1268:     synchronized (getTreeLock ())
1269:       {
1270:         int ncomps = ncomponents;
1271:         Component[] comps = component;
1272:         for (int i = ncomps - 1; i >= 0; --i)
1273:           {
1274:             Component comp = comps[i];
1275:             if (comp != null)
1276:               comp.removeNotify();
1277:           }
1278:         super.removeNotify();
1279:       }
1280:   }
1281: 
1282:   /**
1283:    * Tests whether or not the specified component is contained within
1284:    * this components subtree.
1285:    *
1286:    * @param comp The component to test.
1287:    *
1288:    * @return <code>true</code> if this container is an ancestor of the
1289:    * specified component, <code>false</code> otherwise.
1290:    */
1291:   public boolean isAncestorOf(Component comp)
1292:   {
1293:     synchronized (getTreeLock ())
1294:       {
1295:         while (true)
1296:           {
1297:             if (comp == null)
1298:               return false;
1299:             if (comp == this)
1300:               return true;
1301:             comp = comp.getParent();
1302:           }
1303:       }
1304:   }
1305: 
1306:   /**
1307:    * Returns a string representing the state of this container for
1308:    * debugging purposes.
1309:    *
1310:    * @return A string representing the state of this container.
1311:    */
1312:   protected String paramString()
1313:   {
1314:     if (layoutMgr == null)
1315:       return super.paramString();
1316: 
1317:     StringBuffer sb = new StringBuffer();
1318:     sb.append(super.paramString());
1319:     sb.append(",layout=");
1320:     sb.append(layoutMgr.getClass().getName());
1321:     return sb.toString();
1322:   }
1323: 
1324:   /**
1325:    * Writes a listing of this container to the specified stream starting
1326:    * at the specified indentation point.
1327:    *
1328:    * @param out The <code>PrintStream</code> to write to.
1329:    * @param indent The indentation point.
1330:    */
1331:   public void list(PrintStream out, int indent)
1332:   {
1333:     synchronized (getTreeLock ())
1334:       {
1335:         super.list(out, indent);
1336:         for (int i = 0; i < ncomponents; ++i)
1337:           component[i].list(out, indent + 2);
1338:       }
1339:   }
1340: 
1341:   /**
1342:    * Writes a listing of this container to the specified stream starting
1343:    * at the specified indentation point.
1344:    *
1345:    * @param out The <code>PrintWriter</code> to write to.
1346:    * @param indent The indentation point.
1347:    */
1348:   public void list(PrintWriter out, int indent)
1349:   {
1350:     synchronized (getTreeLock ())
1351:       {
1352:         super.list(out, indent);
1353:         for (int i = 0; i < ncomponents; ++i)
1354:           component[i].list(out, indent + 2);
1355:       }
1356:   }
1357: 
1358:   /**
1359:    * Sets the focus traversal keys for a given traversal operation for this
1360:    * Container.
1361:    *
1362:    * @exception IllegalArgumentException If id is not one of
1363:    * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1364:    * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1365:    * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
1366:    * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS,
1367:    * or if keystrokes contains null, or if any Object in keystrokes is not an
1368:    * AWTKeyStroke, or if any keystroke represents a KEY_TYPED event, or if any
1369:    * keystroke already maps to another focus traversal operation for this
1370:    * Container.
1371:    *
1372:    * @since 1.4
1373:    */
1374:   public void setFocusTraversalKeys(int id,
1375:                     Set<? extends AWTKeyStroke> keystrokes)
1376:   {
1377:     if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1378:         id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1379:         id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1380:         id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1381:       throw new IllegalArgumentException ();
1382: 
1383:     if (keystrokes == null)
1384:       {
1385:         Container parent = getParent ();
1386: 
1387:         while (parent != null)
1388:           {
1389:             if (parent.areFocusTraversalKeysSet (id))
1390:               {
1391:                 keystrokes = parent.getFocusTraversalKeys (id);
1392:                 break;
1393:               }
1394:             parent = parent.getParent ();
1395:           }
1396: 
1397:         if (keystrokes == null)
1398:           keystrokes = KeyboardFocusManager.getCurrentKeyboardFocusManager ().
1399:             getDefaultFocusTraversalKeys (id);
1400:       }
1401: 
1402:     Set sa;
1403:     Set sb;
1404:     Set sc;
1405:     String name;
1406:     switch (id)
1407:       {
1408:       case KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS:
1409:         sa = getFocusTraversalKeys
1410:           (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1411:         sb = getFocusTraversalKeys
1412:           (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1413:         sc = getFocusTraversalKeys
1414:           (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1415:         name = "forwardFocusTraversalKeys";
1416:         break;
1417:       case KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS:
1418:         sa = getFocusTraversalKeys
1419:           (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1420:         sb = getFocusTraversalKeys
1421:           (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1422:         sc = getFocusTraversalKeys
1423:           (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1424:         name = "backwardFocusTraversalKeys";
1425:         break;
1426:       case KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS:
1427:         sa = getFocusTraversalKeys
1428:           (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1429:         sb = getFocusTraversalKeys
1430:           (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1431:         sc = getFocusTraversalKeys
1432:           (KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS);
1433:         name = "upCycleFocusTraversalKeys";
1434:         break;
1435:       case KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS:
1436:         sa = getFocusTraversalKeys
1437:           (KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
1438:         sb = getFocusTraversalKeys
1439:           (KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
1440:         sc = getFocusTraversalKeys
1441:           (KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS);
1442:         name = "downCycleFocusTraversalKeys";
1443:         break;
1444:       default:
1445:         throw new IllegalArgumentException ();
1446:       }
1447: 
1448:     int i = keystrokes.size ();
1449:     Iterator iter = keystrokes.iterator ();
1450: 
1451:     while (--i >= 0)
1452:       {
1453:         Object o = iter.next ();
1454:         if (!(o instanceof AWTKeyStroke)
1455:             || sa.contains (o) || sb.contains (o) || sc.contains (o)
1456:             || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
1457:           throw new IllegalArgumentException ();
1458:       }
1459: 
1460:     if (focusTraversalKeys == null)
1461:       focusTraversalKeys = new Set[4];
1462: 
1463:     keystrokes =
1464:       Collections.unmodifiableSet(new HashSet<AWTKeyStroke>(keystrokes));
1465:     firePropertyChange (name, focusTraversalKeys[id], keystrokes);
1466: 
1467:     focusTraversalKeys[id] = keystrokes;
1468:   }
1469:   
1470:   /**
1471:    * Returns the Set of focus traversal keys for a given traversal operation for
1472:    * this Container.
1473:    *
1474:    * @exception IllegalArgumentException If id is not one of
1475:    * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1476:    * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1477:    * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
1478:    * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS.
1479:    *
1480:    * @since 1.4
1481:    */
1482:   public Set<AWTKeyStroke> getFocusTraversalKeys (int id)
1483:   {
1484:     if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1485:         id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1486:         id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1487:         id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1488:       throw new IllegalArgumentException ();
1489: 
1490:     Set s = null;
1491: 
1492:     if (focusTraversalKeys != null)
1493:       s = focusTraversalKeys[id];
1494: 
1495:     if (s == null && parent != null)
1496:       s = parent.getFocusTraversalKeys (id);
1497: 
1498:     return s == null ? (KeyboardFocusManager.getCurrentKeyboardFocusManager()
1499:                         .getDefaultFocusTraversalKeys(id)) : s;
1500:   }
1501: 
1502:   /**
1503:    * Returns whether the Set of focus traversal keys for the given focus
1504:    * traversal operation has been explicitly defined for this Container.
1505:    * If this method returns false, this Container is inheriting the Set from
1506:    * an ancestor, or from the current KeyboardFocusManager.
1507:    *
1508:    * @exception IllegalArgumentException If id is not one of
1509:    * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1510:    * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1511:    * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS,
1512:    * or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS.
1513:    *
1514:    * @since 1.4
1515:    */
1516:   public boolean areFocusTraversalKeysSet (int id)
1517:   {
1518:     if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
1519:         id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
1520:         id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
1521:         id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
1522:       throw new IllegalArgumentException ();
1523: 
1524:     return focusTraversalKeys != null && focusTraversalKeys[id] != null;
1525:   }
1526: 
1527:   /**
1528:    * Check whether the given Container is the focus cycle root of this
1529:    * Container's focus traversal cycle.  If this Container is a focus
1530:    * cycle root itself, then it will be in two different focus cycles
1531:    * -- it's own, and that of its ancestor focus cycle root's.  In
1532:    * that case, if <code>c</code> is either of those containers, this
1533:    * method will return true.
1534:    *
1535:    * @param c the candidate Container
1536:    *
1537:    * @return true if c is the focus cycle root of the focus traversal
1538:    * cycle to which this Container belongs, false otherwise
1539:    *
1540:    * @since 1.4
1541:    */
1542:   public boolean isFocusCycleRoot (Container c)
1543:   {
1544:     if (this == c
1545:         && isFocusCycleRoot ())
1546:       return true;
1547: 
1548:     Container ancestor = getFocusCycleRootAncestor ();
1549: 
1550:     if (c == ancestor)
1551:       return true;
1552: 
1553:     return false;
1554:   }
1555: 
1556:   /**
1557:    * If this Container is a focus cycle root, set the focus traversal
1558:    * policy that determines the focus traversal order for its
1559:    * children.  If non-null, this policy will be inherited by all
1560:    * inferior focus cycle roots.  If <code>policy</code> is null, this
1561:    * Container will inherit its policy from the closest ancestor focus
1562:    * cycle root that's had its policy set.
1563:    *
1564:    * @param policy the new focus traversal policy for this Container or null
1565:    *
1566:    * @since 1.4
1567:    */
1568:   public void setFocusTraversalPolicy (FocusTraversalPolicy policy)
1569:   {
1570:     focusTraversalPolicy = policy;
1571:   }
1572: 
1573:   /**
1574:    * Return the focus traversal policy that determines the focus
1575:    * traversal order for this Container's children.  This method
1576:    * returns null if this Container is not a focus cycle root.  If the
1577:    * focus traversal policy has not been set explicitly, then this
1578:    * method will return an ancestor focus cycle root's policy instead.
1579:    *
1580:    * @return this Container's focus traversal policy or null
1581:    *
1582:    * @since 1.4
1583:    */
1584:   public FocusTraversalPolicy getFocusTraversalPolicy ()
1585:   {
1586:     if (!isFocusCycleRoot ())
1587:       return null;
1588: 
1589:     if (focusTraversalPolicy == null)
1590:       {
1591:         Container ancestor = getFocusCycleRootAncestor ();
1592: 
1593:     if (ancestor != this && ancestor !=  null)
1594:       return ancestor.getFocusTraversalPolicy ();
1595:     else
1596:       {
1597:         KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager ();
1598: 
1599:         return manager.getDefaultFocusTraversalPolicy ();
1600:       }
1601:       }
1602:     else
1603:       return focusTraversalPolicy;
1604:   }
1605: 
1606:   /**
1607:    * Check whether this Container's focus traversal policy has been
1608:    * explicitly set.  If it has not, then this Container will inherit
1609:    * its focus traversal policy from one of its ancestor focus cycle
1610:    * roots.
1611:    *
1612:    * @return true if focus traversal policy is set, false otherwise
1613:   */
1614:   public boolean isFocusTraversalPolicySet ()
1615:   {
1616:     return focusTraversalPolicy == null;
1617:   }
1618: 
1619:   /**
1620:    * Set whether or not this Container is the root of a focus
1621:    * traversal cycle.  This Container's focus traversal policy
1622:    * determines the order of focus traversal.  Some policies prevent
1623:    * the focus from being transferred between two traversal cycles
1624:    * until an up or down traversal operation is performed.  In that
1625:    * case, normal traversal (not up or down) is limited to this
1626:    * Container and all of this Container's descendents that are not
1627:    * descendents of inferior focus cycle roots.  In the default case
1628:    * however, ContainerOrderFocusTraversalPolicy is in effect, and it
1629:    * supports implicit down-cycle traversal operations.
1630:    *
1631:    * @param focusCycleRoot true if this is a focus cycle root, false otherwise
1632:    *
1633:    * @since 1.4
1634:    */
1635:   public void setFocusCycleRoot (boolean focusCycleRoot)
1636:   {
1637:     this.focusCycleRoot = focusCycleRoot;
1638:   }
1639: 
1640:   /**
1641:    * Set to <code>true</code> if this container provides a focus traversal
1642:    * policy, <code>false</code> when the root container's focus
1643:    * traversal policy should be used.
1644:    *
1645:    * @return <code>true</code> if this container provides a focus traversal
1646:    *        policy, <code>false</code> when the root container's focus
1647:    *        traversal policy should be used
1648:    *
1649:    * @see #setFocusTraversalPolicyProvider(boolean)
1650:    *
1651:    * @since 1.5
1652:    */
1653:   public final boolean isFocusTraversalPolicyProvider()
1654:   {
1655:     return focusTraversalPolicyProvider;
1656:   }
1657: 
1658:   /**
1659:    * Set to <code>true</code> if this container provides a focus traversal
1660:    * policy, <code>false</code> when the root container's focus
1661:    * traversal policy should be used.
1662:    *
1663:    * @param b <code>true</code> if this container provides a focus traversal
1664:    *        policy, <code>false</code> when the root container's focus
1665:    *        traversal policy should be used
1666:    * 
1667:    * @see #isFocusTraversalPolicyProvider()
1668:    *
1669:    * @since 1.5
1670:    */
1671:   public final void setFocusTraversalPolicyProvider(boolean b)
1672:   {
1673:     focusTraversalPolicyProvider = b;
1674:   }
1675: 
1676:   /**
1677:    * Check whether this Container is a focus cycle root.
1678:    *
1679:    * @return true if this is a focus cycle root, false otherwise
1680:    *
1681:    * @since 1.4
1682:    */
1683:   public boolean isFocusCycleRoot ()
1684:   {
1685:     return focusCycleRoot;
1686:   }
1687: 
1688:   /**
1689:    * Transfer focus down one focus traversal cycle.  If this Container
1690:    * is a focus cycle root, then its default component becomes the
1691:    * focus owner, and this Container becomes the current focus cycle
1692:    * root.  No traversal will occur if this Container is not a focus
1693:    * cycle root.
1694:    *
1695:    * @since 1.4
1696:    */
1697:   public void transferFocusDownCycle ()
1698:   {
1699:     if (isFocusCycleRoot())
1700:       {
1701:         KeyboardFocusManager fm =
1702:           KeyboardFocusManager.getCurrentKeyboardFocusManager();
1703:         fm.setGlobalCurrentFocusCycleRoot(this);
1704:         FocusTraversalPolicy policy = getFocusTraversalPolicy();
1705:         Component defaultComponent = policy.getDefaultComponent(this);
1706:         if (defaultComponent != null)
1707:           defaultComponent.requestFocus();
1708:       }
1709:   }
1710: 
1711:   /**
1712:    * Sets the ComponentOrientation property of this container and all components
1713:    * contained within it.
1714:    *
1715:    * @exception NullPointerException If orientation is null
1716:    *
1717:    * @since 1.4
1718:    */
1719:   public void applyComponentOrientation (ComponentOrientation orientation)
1720:   {
1721:     if (orientation == null)
1722:       throw new NullPointerException();
1723: 
1724:     setComponentOrientation(orientation);
1725:     for (int i = 0; i < ncomponents; i++)
1726:       {
1727:         if (component[i] instanceof Container)
1728:              ((Container) component[i]).applyComponentOrientation(orientation); 
1729:           else
1730:              component[i].setComponentOrientation(orientation);
1731:       }
1732:   }
1733: 
1734:   public void addPropertyChangeListener (PropertyChangeListener listener)
1735:   {
1736:     // TODO: Why is this overridden?
1737:     super.addPropertyChangeListener(listener);
1738:   }
1739: 
1740:   public void addPropertyChangeListener (String propertyName,
1741:                                          PropertyChangeListener listener)
1742:   {
1743:     // TODO: Why is this overridden?
1744:     super.addPropertyChangeListener(propertyName, listener);
1745:   }
1746: 
1747: 
1748:   /**
1749:    * Sets the Z ordering for the component <code>comp</code> to
1750:    * <code>index</code>. Components with lower Z order paint above components
1751:    * with higher Z order.
1752:    *
1753:    * @param comp the component for which to change the Z ordering
1754:    * @param index the index to set
1755:    *
1756:    * @throws NullPointerException if <code>comp == null</code>
1757:    * @throws IllegalArgumentException if comp is an ancestor of this container
1758:    * @throws IllegalArgumentException if <code>index</code> is not in
1759:    *         <code>[0, getComponentCount()]</code> for moving between
1760:    *         containers or <code>[0, getComponentCount() - 1]</code> for moving
1761:    *         inside this container
1762:    * @throws IllegalArgumentException if <code>comp == this</code>
1763:    * @throws IllegalArgumentException if <code>comp</code> is a
1764:    *         <code>Window</code>
1765:    *
1766:    * @see #getComponentZOrder(Component)
1767:    *
1768:    * @since 1.5
1769:    */
1770:   public final void setComponentZOrder(Component comp, int index)
1771:   {
1772:     if (comp == null)
1773:       throw new NullPointerException("comp must not be null");
1774:     if (comp instanceof Container && ((Container) comp).isAncestorOf(this))
1775:       throw new IllegalArgumentException("comp must not be an ancestor of "
1776:                                          + "this");
1777:     if (comp instanceof Window)
1778:       throw new IllegalArgumentException("comp must not be a Window");
1779: 
1780:     if (comp == this)
1781:       throw new IllegalArgumentException("cannot add component to itself");
1782: 
1783:     synchronized (getTreeLock())
1784:       {
1785:         // FIXME: Implement reparenting.
1786:         if ( comp.getParent() != this)
1787:           throw new AssertionError("Reparenting is not implemented yet");
1788:         else
1789:           {
1790:             // Find current component index.
1791:             int currentIndex = getComponentZOrder(comp);
1792:             if (currentIndex < index)
1793:               {
1794:                 System.arraycopy(component, currentIndex + 1, component,
1795:                                  currentIndex, index - currentIndex);
1796:               }
1797:             else
1798:               {
1799:                 System.arraycopy(component, index, component, index + 1,
1800:                                  currentIndex - index);
1801:               }
1802:             component[index] = comp;
1803:           }
1804:       }
1805:   }
1806: 
1807:   /**
1808:    * Returns the Z ordering index of <code>comp</code>. If <code>comp</code>
1809:    * is not a child component of this Container, this returns <code>-1</code>.
1810:    *
1811:    * @param comp the component for which to query the Z ordering
1812:    *
1813:    * @return the Z ordering index of <code>comp</code> or <code>-1</code> if
1814:    *         <code>comp</code> is not a child of this Container
1815:    *
1816:    * @see #setComponentZOrder(Component, int)
1817:    *
1818:    * @since 1.5
1819:    */
1820:   public final int getComponentZOrder(Component comp)
1821:   {
1822:     synchronized (getTreeLock())
1823:       {
1824:         int index = -1;
1825:         if (component != null)
1826:           {
1827:             for (int i = 0; i < ncomponents; i++)
1828:               {
1829:                 if (component[i] == comp)
1830:                   {
1831:                     index = i;
1832:                     break;
1833:                   }
1834:               }
1835:           }
1836:         return index;
1837:       }
1838:   }
1839: 
1840:   // Hidden helper methods.
1841: 
1842:   /**
1843:    * Perform a graphics operation on the children of this container.
1844:    * For each applicable child, the visitChild() method will be called
1845:    * to perform the graphics operation.
1846:    *
1847:    * @param gfx The graphics object that will be used to derive new
1848:    * graphics objects for the children.
1849:    *
1850:    * @param visitor Object encapsulating the graphics operation that
1851:    * should be performed.
1852:    *
1853:    * @param lightweightOnly If true, only lightweight components will
1854:    * be visited.
1855:    */
1856:   private void visitChildren(Graphics gfx, GfxVisitor visitor,
1857:                              boolean lightweightOnly)
1858:   {
1859:     synchronized (getTreeLock())
1860:       {
1861:         for (int i = ncomponents - 1; i >= 0; --i)
1862:           {
1863:             Component comp = component[i];
1864:             boolean applicable = comp.isVisible()
1865:                                  && (comp.isLightweight() || ! lightweightOnly);
1866:             
1867:             if (applicable)
1868:               visitChild(gfx, visitor, comp);
1869:           }
1870:       }
1871:   }
1872: 
1873:   /**
1874:    * Perform a graphics operation on a child. A translated and clipped
1875:    * graphics object will be created, and the visit() method of the
1876:    * visitor will be called to perform the operation.
1877:    *
1878:    * @param gfx The graphics object that will be used to derive new
1879:    * graphics objects for the child.
1880:    *
1881:    * @param visitor Object encapsulating the graphics operation that
1882:    * should be performed.
1883:    *
1884:    * @param comp The child component that should be visited.
1885:    */
1886:   private void visitChild(Graphics gfx, GfxVisitor visitor,
1887:                           Component comp)
1888:   {
1889:     Rectangle bounds = comp.getBounds();
1890:     
1891:     if(!gfx.hitClip(bounds.x,bounds.y, bounds.width, bounds.height))
1892:       return;
1893:     Graphics g2 = gfx.create(bounds.x, bounds.y, bounds.width,
1894:                              bounds.height);
1895:     try
1896:       {
1897:         g2.setFont(comp.getFont());
1898:         visitor.visit(comp, g2);
1899:       }
1900:     finally
1901:       {
1902:         g2.dispose();
1903:       }
1904:   }
1905: 
1906:   /**
1907:    * Overridden to dispatch events to lightweight descendents.
1908:    *
1909:    * @param e the event to dispatch.
1910:    */
1911:   void dispatchEventImpl(AWTEvent e)
1912:   {
1913:     LightweightDispatcher dispatcher = LightweightDispatcher.getInstance(); 
1914:     if (! isLightweight() && dispatcher.dispatchEvent(e))
1915:       {
1916:         // Some lightweight descendent got this event dispatched. Consume
1917:         // it and let the peer handle it.
1918:         e.consume();
1919:         ComponentPeer p = peer;
1920:         if (p != null)
1921:           p.handleEvent(e);
1922:       }
1923:     else
1924:       {
1925:         super.dispatchEventImpl(e);
1926:       }
1927:   }
1928: 
1929:   /**
1930:    * This is called by the lightweight dispatcher to avoid recursivly
1931:    * calling into the lightweight dispatcher.
1932:    *
1933:    * @param e the event to dispatch
1934:    *
1935:    * @see LightweightDispatcher#redispatch(MouseEvent, Component, int)
1936:    */
1937:   void dispatchNoLightweight(AWTEvent e)
1938:   {
1939:     super.dispatchEventImpl(e);
1940:   }
1941: 
1942:   /**
1943:    * Tests if this container has an interest in the given event id.
1944:    *
1945:    * @param eventId The event id to check.
1946:    *
1947:    * @return <code>true</code> if a listener for the event id exists or
1948:    *         if the eventMask is set for the event id.
1949:    *
1950:    * @see java.awt.Component#eventTypeEnabled(int)
1951:    */
1952:   boolean eventTypeEnabled(int eventId)
1953:   {
1954:     if(eventId <= ContainerEvent.CONTAINER_LAST 
1955:        && eventId >= ContainerEvent.CONTAINER_FIRST)
1956:       return containerListener != null
1957:         || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0;
1958:       else 
1959:         return super.eventTypeEnabled(eventId);
1960:   }
1961: 
1962:   // This is used to implement Component.transferFocus.
1963:   Component findNextFocusComponent(Component child)
1964:   {
1965:     synchronized (getTreeLock ())
1966:       {
1967:         int start, end;
1968:         if (child != null)
1969:           {
1970:             for (start = 0; start < ncomponents; ++start)
1971:               {
1972:                 if (component[start] == child)
1973:                   break;
1974:               }
1975:             end = start;
1976:             // This special case lets us be sure to terminate.
1977:             if (end == 0)
1978:               end = ncomponents;
1979:             ++start;
1980:           }
1981:         else
1982:           {
1983:             start = 0;
1984:             end = ncomponents;
1985:           }
1986: 
1987:         for (int j = start; j != end; ++j)
1988:           {
1989:             if (j >= ncomponents)
1990:               {
1991:                 // The JCL says that we should wrap here.  However, that
1992:                 // seems wrong.  To me it seems that focus order should be
1993:                 // global within in given window.  So instead if we reach
1994:                 // the end we try to look in our parent, if we have one.
1995:                 if (parent != null)
1996:                   return parent.findNextFocusComponent(this);
1997:                 j -= ncomponents;
1998:               }
1999:             if (component[j] instanceof Container)
2000:               {
2001:                 Component c = component[j];
2002:                 c = c.findNextFocusComponent(null);
2003:                 if (c != null)
2004:                   return c;
2005:               }
2006:             else if (component[j].isFocusTraversable())
2007:               return component[j];
2008:           }
2009: 
2010:         return null;
2011:       }
2012:   }
2013: 
2014:   /**
2015:    * Fires hierarchy events to the children of this container and this
2016:    * container itself. This overrides {@link Component#fireHierarchyEvent}
2017:    * in order to forward this event to all children.
2018:    */
2019:   void fireHierarchyEvent(int id, Component changed, Container parent,
2020:                           long flags)
2021:   {
2022:     // Only propagate event if there is actually a listener waiting for it.
2023:     if ((id == HierarchyEvent.HIERARCHY_CHANGED && numHierarchyListeners > 0)
2024:         || ((id == HierarchyEvent.ANCESTOR_MOVED
2025:              || id == HierarchyEvent.ANCESTOR_RESIZED)
2026:             && numHierarchyBoundsListeners > 0))
2027:       {
2028:         for (int i = 0; i < ncomponents; i++)
2029:           component[i].fireHierarchyEvent(id, changed, parent, flags);
2030:         super.fireHierarchyEvent(id, changed, parent, flags);
2031:       }
2032:   }
2033: 
2034:   /**
2035:    * Adjusts the number of hierarchy listeners of this container and all of
2036:    * its parents. This is called by the add/remove listener methods and
2037:    * structure changing methods in Container.
2038:    *
2039:    * @param type the type, either {@link AWTEvent#HIERARCHY_BOUNDS_EVENT_MASK}
2040:    *        or {@link AWTEvent#HIERARCHY_EVENT_MASK}
2041:    * @param delta the number of listeners added or removed
2042:    */
2043:   void updateHierarchyListenerCount(long type, int delta)
2044:   {
2045:     if (type == AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK)
2046:       numHierarchyBoundsListeners += delta;
2047:     else if (type == AWTEvent.HIERARCHY_EVENT_MASK)
2048:       numHierarchyListeners += delta;
2049:     else
2050:       assert false : "Should not reach here";
2051: 
2052:     if (parent != null)
2053:       parent.updateHierarchyListenerCount(type, delta);
2054:   }
2055: 
2056:   /**
2057:    * Notifies interested listeners about resizing or moving the container.
2058:    * This performs the super behaviour (sending component events) and
2059:    * additionally notifies any hierarchy bounds listeners on child components.
2060:    *
2061:    * @param resized true if the component has been resized, false otherwise
2062:    * @param moved true if the component has been moved, false otherwise
2063:    */
2064:   void notifyReshape(boolean resized, boolean moved)
2065:   {
2066:     // Notify component listeners.
2067:     super.notifyReshape(resized, moved);
2068: 
2069:     if (ncomponents > 0)
2070:       {
2071:         // Notify hierarchy bounds listeners.
2072:         if (resized)
2073:           {
2074:             for (int i = 0; i < getComponentCount(); i++)
2075:               {
2076:                 Component child = getComponent(i);
2077:                 child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED,
2078:                                          this, parent, 0);
2079:               }
2080:           }
2081:         if (moved)
2082:           {
2083:             for (int i = 0; i < getComponentCount(); i++)
2084:               {
2085:                 Component child = getComponent(i);
2086:                 child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED,
2087:                                          this, parent, 0);
2088:               }
2089:           }
2090:       }
2091:   }
2092: 
2093:   private void addNotifyContainerChildren()
2094:   {
2095:     synchronized (getTreeLock ())
2096:       {
2097:         for (int i = ncomponents;  --i >= 0; )
2098:           {
2099:             component[i].addNotify();
2100:           }
2101:       }
2102:   }
2103: 
2104:   /**
2105:    * Deserialize this Container:
2106:    * <ol>
2107:    * <li>Read from the stream the default serializable fields.</li>
2108:    * <li>Read a list of serializable ContainerListeners as optional
2109:    * data.  If the list is null, no listeners will be registered.</li>
2110:    * <li>Read this Container's FocusTraversalPolicy as optional data.
2111:    * If this is null, then this Container will use a
2112:    * DefaultFocusTraversalPolicy.</li>
2113:    * </ol>
2114:    *
2115:    * @param s the stream to read from
2116:    * @throws ClassNotFoundException if deserialization fails
2117:    * @throws IOException if the stream fails
2118:    */
2119:   private void readObject (ObjectInputStream s)
2120:     throws ClassNotFoundException, IOException
2121:   {
2122:     s.defaultReadObject ();
2123:     String key = (String) s.readObject ();
2124:     while (key != null)
2125:       {
2126:         Object object = s.readObject ();
2127:         if ("containerL".equals (key))
2128:           addContainerListener((ContainerListener) object);
2129:         // FIXME: under what key is the focus traversal policy stored?
2130:         else if ("focusTraversalPolicy".equals (key))
2131:           setFocusTraversalPolicy ((FocusTraversalPolicy) object);
2132: 
2133:         key = (String) s.readObject();
2134:       }
2135:   }
2136: 
2137:   /**
2138:    * Serialize this Container:
2139:    * <ol>
2140:    * <li>Write to the stream the default serializable fields.</li>
2141:    * <li>Write the list of serializable ContainerListeners as optional
2142:    * data.</li>
2143:    * <li>Write this Container's FocusTraversalPolicy as optional data.</li>
2144:    * </ol>
2145:    *
2146:    * @param s the stream to write to
2147:    * @throws IOException if the stream fails
2148:    */
2149:   private void writeObject (ObjectOutputStream s) throws IOException
2150:   {
2151:     s.defaultWriteObject ();
2152:     AWTEventMulticaster.save (s, "containerL", containerListener);
2153:     if (focusTraversalPolicy instanceof Serializable)
2154:       s.writeObject (focusTraversalPolicy);
2155:     else
2156:       s.writeObject (null);
2157:   }
2158: 
2159:   // Nested classes.
2160: 
2161:   /* The following classes are used in concert with the
2162:      visitChildren() method to implement all the graphics operations
2163:      that requires traversal of the containment hierarchy. */
2164: 
2165:   abstract static class GfxVisitor
2166:   {
2167:     public abstract void visit(Component c, Graphics gfx);
2168:   }
2169: 
2170:   static class GfxPaintVisitor extends GfxVisitor
2171:   {
2172:     public static final GfxVisitor INSTANCE = new GfxPaintVisitor();
2173:     
2174:     public void visit(Component c, Graphics gfx)
2175:     {
2176:       c.paint(gfx);
2177:     }
2178:   }
2179: 
2180:   static class GfxPrintVisitor extends GfxVisitor
2181:   {
2182:     public static final GfxVisitor INSTANCE = new GfxPrintVisitor();
2183:     
2184:     public void visit(Component c, Graphics gfx)
2185:     {
2186:       c.print(gfx);
2187:     }
2188:   }
2189: 
2190:   static class GfxPaintAllVisitor extends GfxVisitor
2191:   {
2192:     public static final GfxVisitor INSTANCE = new GfxPaintAllVisitor();
2193: 
2194:     public void visit(Component c, Graphics gfx)
2195:     {
2196:       c.paintAll(gfx);
2197:     }
2198:   }
2199: 
2200:   static class GfxPrintAllVisitor extends GfxVisitor
2201:   {
2202:     public static final GfxVisitor INSTANCE = new GfxPrintAllVisitor();
2203: 
2204:     public void visit(Component c, Graphics gfx)
2205:     {
2206:       c.printAll(gfx);
2207:     }
2208:   }
2209: 
2210:   /**
2211:    * This class provides accessibility support for subclasses of container.
2212:    *
2213:    * @author Eric Blake (ebb9@email.byu.edu)
2214:    *
2215:    * @since 1.3
2216:    */
2217:   protected class AccessibleAWTContainer extends AccessibleAWTComponent
2218:   {
2219:     /**
2220:      * Compatible with JDK 1.4+.
2221:      */
2222:     private static final long serialVersionUID = 5081320404842566097L;
2223: 
2224:     /**
2225:      * The handler to fire PropertyChange when children are added or removed.
2226:      *
2227:      * @serial the handler for property changes
2228:      */
2229:     protected ContainerListener accessibleContainerHandler
2230:       = new AccessibleContainerHandler();
2231: 
2232:     /**
2233:      * The default constructor.
2234:      */
2235:     protected AccessibleAWTContainer()
2236:     {
2237:       Container.this.addContainerListener(accessibleContainerHandler);
2238:     }
2239: 
2240:     /**
2241:      * Return the number of accessible children of the containing accessible
2242:      * object (at most the total number of its children).
2243:      *
2244:      * @return the number of accessible children
2245:      */
2246:     public int getAccessibleChildrenCount()
2247:     {
2248:       synchronized (getTreeLock ())
2249:         {
2250:           int count = 0;
2251:           int i = component == null ? 0 : component.length;
2252:           while (--i >= 0)
2253:             if (component[i] instanceof Accessible)
2254:               count++;
2255:           return count;
2256:         }
2257:     }
2258: 
2259:     /**
2260:      * Return the nth accessible child of the containing accessible object.
2261:      *
2262:      * @param i the child to grab, zero-based
2263:      * @return the accessible child, or null
2264:      */
2265:     public Accessible getAccessibleChild(int i)
2266:     {
2267:       synchronized (getTreeLock ())
2268:         {
2269:           if (component == null)
2270:             return null;
2271:           int index = -1;
2272:           while (i >= 0 && ++index < component.length)
2273:             if (component[index] instanceof Accessible)
2274:               i--;
2275:           if (i < 0)
2276:             return (Accessible) component[index];
2277:           return null;
2278:         }
2279:     }
2280: 
2281:     /**
2282:      * Return the accessible child located at point (in the parent's
2283:      * coordinates), if one exists.
2284:      *
2285:      * @param p the point to look at
2286:      *
2287:      * @return an accessible object at that point, or null
2288:      *
2289:      * @throws NullPointerException if p is null
2290:      */
2291:     public Accessible getAccessibleAt(Point p)
2292:     {
2293:       Component c = getComponentAt(p.x, p.y);
2294:       return c != Container.this && c instanceof Accessible ? (Accessible) c
2295:         : null;
2296:     }
2297: 
2298:     /**
2299:      * This class fires a <code>PropertyChange</code> listener, if registered,
2300:      * when children are added or removed from the enclosing accessible object.
2301:      *
2302:      * @author Eric Blake (ebb9@email.byu.edu)
2303:      *
2304:      * @since 1.3
2305:      */
2306:     protected class AccessibleContainerHandler implements ContainerListener
2307:     {
2308:       /**
2309:        * Default constructor.
2310:        */
2311:       protected AccessibleContainerHandler()
2312:       {
2313:         // Nothing to do here.
2314:       }
2315: 
2316:       /**
2317:        * Fired when a component is added; forwards to the PropertyChange
2318:        * listener.
2319:        *
2320:        * @param e the container event for adding
2321:        */
2322:       public void componentAdded(ContainerEvent e)
2323:       {
2324:         AccessibleAWTContainer.this.firePropertyChange
2325:           (ACCESSIBLE_CHILD_PROPERTY, null, e.getChild());
2326:       }
2327: 
2328:       /**
2329:        * Fired when a component is removed; forwards to the PropertyChange
2330:        * listener.
2331:        *
2332:        * @param e the container event for removing
2333:        */
2334:       public void componentRemoved(ContainerEvent e)
2335:       {
2336:         AccessibleAWTContainer.this.firePropertyChange
2337:           (ACCESSIBLE_CHILD_PROPERTY, e.getChild(), null);
2338:       }
2339:     } // class AccessibleContainerHandler
2340:   } // class AccessibleAWTContainer
2341: } // class Container