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