Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)
Frames | No Frames

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
Overview Package Class Use Source Tree Index Deprecated About
GNU Classpath (0.95)

AltStyle によって変換されたページ (->オリジナル) /